Przeglądaj źródła

new: assira.ui: CSS4 angle

Ranides Atterwim 1 rok temu
rodzic
commit
25d8280fac

+ 2 - 1
assira.ui/src/main/antlr4/imports/CssColor.g4

@@ -1,6 +1,6 @@
 grammar CssColor;
 
-import BaseNumbers;
+import BaseNumbers, CssUnit;
 
 color
     : colorHSL      #color_hsl
@@ -34,6 +34,7 @@ colorHEX
 
 componentHue
     : numberInt
+    | angle
     ;
 
 componentSaturation

+ 16 - 8
assira.ui/src/main/antlr4/imports/CssUnit.g4

@@ -3,15 +3,14 @@ grammar CssUnit;
 import BaseNumbers;
 
 length:
-    number unit
+    number unitLength
     ;
 
-unit
-    : unitAbs
-    | unitRel
+angle:
+    number unitAngle?
     ;
 
-unitAbs
+unitLength
     : CSS2_UNIT_PX
     | CSS2_UNIT_PT
     | CSS2_UNIT_CM
@@ -19,10 +18,8 @@ unitAbs
     | CSS2_UNIT_Q
     | CSS2_UNIT_IN
     | CSS2_UNIT_PC
-    ;
 
-unitRel
-    : CSS2_UNIT_EM
+    | CSS2_UNIT_EM
     | CSS2_UNIT_EX
     | CSS2_UNIT_CAP
     | CSS2_UNIT_CH
@@ -44,6 +41,13 @@ unitRel
     | CSS2_UNIT_VI
     ;
 
+unitAngle
+    : CSS4_DEG
+    | CSS4_GRAD
+    | CSS4_RAD
+    | CSS4_TURN
+    ;
+
 CSS2_UNIT_PX : 'px';
 CSS2_UNIT_PT : 'pt';
 CSS2_UNIT_CM : 'cm';
@@ -73,3 +77,7 @@ CSS2_UNIT_VMIN : 'vmin';
 CSS2_UNIT_VB : 'vb';
 CSS2_UNIT_VI : 'vi';
 
+CSS4_DEG :  'deg';
+CSS4_GRAD : 'grad';
+CSS4_RAD :  'rad';
+CSS4_TURN : 'turn';

+ 8 - 0
assira.ui/src/main/java/net/ranides/assira/ui/model/CssUnitAngle.java

@@ -0,0 +1,8 @@
+package net.ranides.assira.ui.model;
+
+public enum CssUnitAngle {
+    DEG,
+    GRAD,
+    RAD,
+    TURN
+}

+ 2 - 2
assira.ui/src/main/java/net/ranides/assira/ui/parsers/ParseCssColor.java

@@ -337,14 +337,14 @@ public class ParseCssColor {
             return new Color(r, g, b, alpha);
         })
         .mapRule("colorHSL", node -> {
-            float h = ParsePrimitives.parseInt(node.child("@h")) / 360.0f;
+            float h = ParseCssUnit.angle(node.child("@h").text()).floatValue() / 360.0f;
             float s = ParsePrimitives.parsePct(node.child("@s")) / 100.0f;
             float v = ParsePrimitives.parsePct(node.child("@l")) / 100.0f;
 
             return Color.getHSBColor(h,s,v);
         })
         .mapRule("colorHSLA", node -> {
-            float h = ParsePrimitives.parseInt(node.child("@h")) / 360.0f;
+            float h = ParseCssUnit.angle(node.child("@h").text()).floatValue() / 360.0f;
             float s = ParsePrimitives.parsePct(node.child("@s")) / 100.0f;
             float v = ParsePrimitives.parsePct(node.child("@l")) / 100.0f;
             int alpha = Math.round(255 * ParsePrimitives.parseFloat(node.child("@alpha")));

+ 45 - 3
assira.ui/src/main/java/net/ranides/assira/ui/parsers/ParseCssUnit.java

@@ -5,6 +5,7 @@ import net.ranides.assira.generic.ValueUtils;
 import net.ranides.assira.grammar.G4Node;
 import net.ranides.assira.grammar.G4Selector;
 import net.ranides.assira.grammar.G4SelectorBuilder;
+import net.ranides.assira.ui.model.CssUnitAngle;
 import net.ranides.assira.ui.model.CssUnit;
 import net.ranides.grammars.generated.UiGrammarParser;
 
@@ -14,8 +15,8 @@ import java.awt.*;
 @UtilityClass
 public class ParseCssUnit {
 
-    public static final G4Selector<CssUnit> UNIT = new G4SelectorBuilder<CssUnit>()
-        .withName("CssUnit:UNIT")
+    public static final G4Selector<CssUnit> UNIT_LENGTH = new G4SelectorBuilder<CssUnit>()
+        .withName("CssUnit:UNIT_LENGTH")
         .withParser(GrammarBase.PARSER)
         .valueForToken(UiGrammarParser.CSS2_UNIT_PX, CssUnit.PX)
         .valueForToken(UiGrammarParser.CSS2_UNIT_PT, CssUnit.PT)
@@ -47,17 +48,36 @@ public class ParseCssUnit {
         .valueForToken(UiGrammarParser.CSS2_UNIT_VMIN, CssUnit.VMIN)
         .prepare();
 
+    public static final G4Selector<CssUnitAngle> UNIT_ANGLE = new G4SelectorBuilder<CssUnitAngle>()
+        .withName("CssUnit:UNIT")
+        .withParser(GrammarBase.PARSER)
+        .valueForToken(UiGrammarParser.CSS4_DEG, CssUnitAngle.DEG)
+        .valueForToken(UiGrammarParser.CSS4_RAD, CssUnitAngle.RAD)
+        .valueForToken(UiGrammarParser.CSS4_GRAD, CssUnitAngle.GRAD)
+        .valueForToken(UiGrammarParser.CSS4_TURN, CssUnitAngle.TURN)
+        .prepare();
+
     public static final G4Selector<Integer> LENGTH = new G4SelectorBuilder<Integer>()
         .withName("CssUnit:LENGTH")
         .withParser(GrammarBase.PARSER)
         .mapRule(UiGrammarParser.RULE_length, node -> {
             Number number = ParsePrimitives.parseNumber(node.child("number"));
-            CssUnit unit = UNIT.single(node.child("unit"));
+            CssUnit unit = UNIT_LENGTH.single(node.child("unitLength"));
             return Math.round(length(node, number, unit).floatValue());
 
         })
         .prepare();
 
+    public static final G4Selector<Double> ANGLE = new G4SelectorBuilder<Double>()
+        .withName("CssUnit:ANGLE")
+        .withParser(GrammarBase.PARSER)
+        .mapRule(UiGrammarParser.RULE_angle, node -> {
+            Number number = ParsePrimitives.parseNumber(node.child("number"));
+            CssUnitAngle unit = UNIT_ANGLE.optional(node).orElse(CssUnitAngle.DEG);
+            return angle(number, unit).doubleValue();
+        })
+        .prepare();
+
     public static int length(JComponent component, String value) {
         return GrammarBase.parseSingle(LENGTH, "length", component, value);
     }
@@ -129,6 +149,28 @@ public class ParseCssUnit {
         }
     }
 
+    public static Number angle(String value) {
+        return GrammarBase.parseSingle(ANGLE, "angle", value);
+    }
+
+    public static Number angle(Number number, CssUnitAngle unit) {
+        double v = number.doubleValue();
+
+        switch (unit) {
+            case DEG:
+                return number;
+            case RAD:
+                return 180.0 * v / Math.PI;
+            case GRAD:
+                return 0.9 * v;
+            case TURN:
+                return 360.0 * v;
+
+            default:
+                throw new UnsupportedOperationException("Unsupported unit: " + unit);
+        }
+    }
+
     private static double computeEm(JComponent component) {
         return 1.3333 * component.getFont().getSize();
     }

+ 3 - 5
assira.ui/src/test/java/net/ranides/assira/ui/parsers/GrammarBaseTest.java

@@ -10,10 +10,6 @@ import net.ranides.assira.io.ResourceUtils;
 import net.ranides.assira.junit.NewAssert;
 import net.ranides.assira.system.HostSystem;
 import net.ranides.assira.text.StrAppender;
-import net.ranides.assira.ui.parsers.ParseCssBorder;
-import net.ranides.assira.ui.parsers.ParseCssColor;
-import net.ranides.assira.ui.parsers.ParseCssUnit;
-import net.ranides.assira.ui.parsers.ParsePrimitives;
 import net.ranides.grammars.generated.UiGrammarLexer;
 import net.ranides.grammars.generated.UiGrammarParser;
 import org.junit.Test;
@@ -117,8 +113,10 @@ public class GrammarBaseTest {
         info.use(ParsePrimitives.INT);
         info.use(ParsePrimitives.REAL);
         info.use(ParsePrimitives.CODE);
-        info.use(ParseCssUnit.UNIT);
+        info.use(ParseCssUnit.UNIT_LENGTH);
+        info.use(ParseCssUnit.UNIT_ANGLE);
         info.use(ParseCssUnit.LENGTH);
+        info.use(ParseCssUnit.ANGLE);
         info.use(ParseCssColor.COLOR);
         info.use(ParseCssBorder.BORDER_STYLE);
         info.use(ParseCssBorder.BORDER_SIZE);

+ 6 - 6
assira.ui/src/test/java/net/ranides/assira/ui/parsers/ParseCssColorTest.java

@@ -70,16 +70,16 @@ public class ParseCssColorTest {
     public void parseColorHSL() {
 
         assertEquals(new Color(0,128,0), ParseCssColor.color("hsl(120, 100%, 50%)"));
-        assertEquals(new Color(120,191,48), ParseCssColor.color("hsl(90, 75%, 75%)"));
-        assertEquals(new Color(191,191,48), ParseCssColor.color("hsl(60, 75%, 75%)"));
+        assertEquals(new Color(120,191,48), ParseCssColor.color("hsl(100grad, 75%, 75%)"));
+        assertEquals(new Color(191,191,48), ParseCssColor.color("hsl(60deg, 75%, 75%)"));
 
         assertEquals(new Color(0,128,0,0), ParseCssColor.color("hsl(120, 100%, 50%, 0)"));
-        assertEquals(new Color(120,191,48,64), ParseCssColor.color("hsl(90, 75%, 75%, 0.25)"));
-        assertEquals(new Color(191,191,48,191), ParseCssColor.color("hsl(60, 75%, 75%, 0.75)"));
+        assertEquals(new Color(120,191,48,64), ParseCssColor.color("hsl(100grad, 75%, 75%, 0.25)"));
+        assertEquals(new Color(191,191,48,191), ParseCssColor.color("hsl(60deg, 75%, 75%, 0.75)"));
 
         assertEquals(new Color(0,128,0,0), ParseCssColor.color("hsla(120, 100%, 50%, 0)"));
-        assertEquals(new Color(120,191,48,64), ParseCssColor.color("hsla(90, 75%, 75%, 0.25)"));
-        assertEquals(new Color(191,191,48,191), ParseCssColor.color("hsla(60, 75%, 75%, 0.75)"));
+        assertEquals(new Color(120,191,48,64), ParseCssColor.color("hsla(0.25turn, 75%, 75%, 0.25)"));
+        assertEquals(new Color(191,191,48,191), ParseCssColor.color("hsla(1.05rad, 75%, 75%, 0.75)"));
 
         NewAssert.assertThrows(IllegalArgumentException.class, ()->{
             ParseCssColor.color("hsl(x");

+ 9 - 1
assira.ui/src/test/java/net/ranides/assira/ui/parsers/ParseCssUnitTest.java

@@ -58,5 +58,13 @@ public class ParseCssUnitTest {
         assertEquals(120, ParseCssUnit.length(button, "100vb"));
     }
 
-
+    @Test
+    public void angle() {
+        assertEquals(360.0, ParseCssUnit.angle("360").doubleValue(), 0.01);
+        assertEquals(180.0, ParseCssUnit.angle("180deg").doubleValue(), 0.01);
+        assertEquals(720.0, ParseCssUnit.angle("2turn").doubleValue(), 0.01);
+        assertEquals(90.0, ParseCssUnit.angle("100grad").doubleValue(), 0.01);
+        assertEquals(135.0, ParseCssUnit.angle("150grad").doubleValue(), 0.01);
+        assertEquals(180.0, ParseCssUnit.angle("3.1415rad").doubleValue(), 0.01);
+    }
 }

+ 8 - 4
assira.ui/src/test/resources/grammars/CssCoverage.txt

@@ -42,6 +42,10 @@
 1: CSS2_UNIT_VMIN
 1: CSS2_UNIT_VW
 1: CSS2_none
+1: CSS4_DEG
+1: CSS4_GRAD
+1: CSS4_RAD
+1: CSS4_TURN
 1: DOT
 1: GT
 1: LB
@@ -63,6 +67,7 @@
 0: SWING_BORDER_lowered
 0: SWING_BORDER_raised
 1: WS
+1: angle
 0: border
 1: borderCSS
 0: borderCSS_Style
@@ -95,7 +100,7 @@
 1: colorRGBA
 1: colorTr <= COLOR_TRANSPARENT
 0: componentAlpha
-1: componentHue <= numberInt
+0: componentHue
 1: componentLightness <= numberPct
 1: componentRGB <= numberInt
 1: componentSaturation <= numberPct
@@ -113,6 +118,5 @@
 0: root_color
 0: root_colors
    0: root_colors#color_list
-0: unit
-0: unitAbs
-0: unitRel
+0: unitAngle
+0: unitLength