Ignore:
Timestamp:
2015-02-19T15:22:49+01:00 (9 years ago)
Author:
bastiK
Message:

MapCSS: new @supports rule

Implementation should be mostly compatible with
the CSS Conditional 3 draft [2].

This is similar to @media, which was previously misused
for this purpose and is now deprecated.

refs:
[1] https://wiki.openstreetmap.org/wiki/MapCSS/0.2/Proposal_media_query
[2] http://dev.w3.org/csswg/css-conditional/

Location:
trunk/src/org/openstreetmap/josm/gui/mappaint
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/mappaint/BoxTextElemStyle.java

    r7621 r8087  
    119119
    120120        HorizontalTextAlignment hAlign = HorizontalTextAlignment.RIGHT;
    121         Keyword hAlignKW = c.get("text-anchor-horizontal", Keyword.RIGHT, Keyword.class);
     121        Keyword hAlignKW = c.get(TEXT_ANCHOR_HORIZONTAL, Keyword.RIGHT, Keyword.class);
    122122        if ("left".equals(hAlignKW.val)) {
    123123            hAlign = HorizontalTextAlignment.LEFT;
     
    128128        }
    129129        VerticalTextAlignment vAlign = VerticalTextAlignment.BOTTOM;
    130         String vAlignStr = c.get("text-anchor-vertical", Keyword.BOTTOM, Keyword.class).val;
     130        String vAlignStr = c.get(TEXT_ANCHOR_VERTICAL, Keyword.BOTTOM, Keyword.class).val;
    131131        if ("above".equals(vAlignStr)) {
    132132            vAlign = VerticalTextAlignment.ABOVE;
  • trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java

    r8085 r8087  
    1414public abstract class ElemStyle implements StyleKeys {
    1515
    16     protected static final String[] ICON_KEYS = {"icon-image", "icon-width", "icon-height", "icon-opacity", "icon-offset-x", "icon-offset-y"};
    17     protected static final String[] REPEAT_IMAGE_KEYS = {"repeat-image", "repeat-image-width", "repeat-image-height", "repeat-image-opacity", null, null};
     16    protected static final int ICON_IMAGE_IDX = 0;
     17    protected static final int ICON_WIDTH_IDX = 1;
     18    protected static final int ICON_HEIGHT_IDX = 2;
     19    protected static final int ICON_OPACITY_IDX = 3;
     20    protected static final int ICON_OFFSET_X_IDX = 4;
     21    protected static final int ICON_OFFSET_Y_IDX = 5;
     22    public static final String[] ICON_KEYS = {ICON_IMAGE, ICON_WIDTH, ICON_HEIGHT, ICON_OPACITY, ICON_OFFSET_X, ICON_OFFSET_Y};
     23    public static final String[] REPEAT_IMAGE_KEYS = {REPEAT_IMAGE, REPEAT_IMAGE_WIDTH, REPEAT_IMAGE_HEIGHT, REPEAT_IMAGE_OPACITY, null, null};
    1824
    1925    public float major_z_index;
     
    3137
    3238    protected ElemStyle(Cascade c, float default_major_z_index) {
    33         major_z_index = c.get("major-z-index", default_major_z_index, Float.class);
     39        major_z_index = c.get(MAJOR_Z_INDEX, default_major_z_index, Float.class);
    3440        z_index = c.get(Z_INDEX, 0f, Float.class);
    3541        object_z_index = c.get(OBJECT_Z_INDEX, 0f, Float.class);
     
    177183
    178184    protected static Font getFont(Cascade c, String s) {
    179         String name = c.get("font-family", getDefaultFontName(), String.class);
    180         float size = c.get("font-size", getDefaultFontSize(), Float.class);
     185        String name = c.get(FONT_FAMILY, getDefaultFontName(), String.class);
     186        float size = c.get(FONT_SIZE, getDefaultFontSize(), Float.class);
    181187        int weight = Font.PLAIN;
    182         if ("bold".equalsIgnoreCase(c.get("font-weight", null, String.class))) {
     188        if ("bold".equalsIgnoreCase(c.get(FONT_WEIGHT, null, String.class))) {
    183189            weight = Font.BOLD;
    184190        }
    185191        int style = Font.PLAIN;
    186         if ("italic".equalsIgnoreCase(c.get("font-style", null, String.class))) {
     192        if ("italic".equalsIgnoreCase(c.get(FONT_STYLE, null, String.class))) {
    187193            style = Font.ITALIC;
    188194        }
  • trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java

    r8073 r8087  
    4040    private BasicStroke dashesLine;
    4141
    42     protected enum LineType {
     42    public enum LineType {
    4343        NORMAL("", 3f),
    4444        CASING("casing-", 2f),
     
    214214
    215215        Integer cap = null;
    216         Keyword capKW = c.get(type.prefix + "linecap", null, Keyword.class);
     216        Keyword capKW = c.get(type.prefix + LINECAP, null, Keyword.class);
    217217        if (capKW != null) {
    218218            if ("none".equals(capKW.val)) {
     
    229229
    230230        Integer join = null;
    231         Keyword joinKW = c.get(type.prefix + "linejoin", null, Keyword.class);
     231        Keyword joinKW = c.get(type.prefix + LINEJOIN, null, Keyword.class);
    232232        if (joinKW != null) {
    233233            if ("round".equals(joinKW.val)) {
     
    243243        }
    244244
    245         float miterlimit = c.get(type.prefix + "miterlimit", 10f, Float.class);
     245        float miterlimit = c.get(type.prefix + MITERLIMIT, 10f, Float.class);
    246246        if (miterlimit < 1f) {
    247247            miterlimit = 10f;
  • trunk/src/org/openstreetmap/josm/gui/mappaint/StyleKeys.java

    r8085 r8087  
    1212    String FILL_IMAGE = "fill-image";
    1313    String FILL_OPACITY = "fill-opacity";
     14    String FONT_FAMILY = "font-family";
     15    String FONT_SIZE = "font-size";
     16    String FONT_STYLE = "font-style";
     17    String FONT_WEIGHT = "font-weight";
    1418    String ICON_IMAGE = "icon-image";
     19    String ICON_HEIGHT = "icon-height";
     20    String ICON_OFFSET_X = "icon-offset-x";
     21    String ICON_OFFSET_Y = "icon-offset-y";
     22    String ICON_OPACITY = "icon-opacity";
     23    String ICON_WIDTH = "icon-width";
     24    String LINECAP = "linecap";
     25    String LINEJOIN = "linejoin";
     26    String MAJOR_Z_INDEX = "major-z-index";
     27    String MITERLIMIT = "miterlimit";
    1528    String MODIFIER = "modifier";
    1629    String OBJECT_Z_INDEX = "object-z-index";
     
    1831    String OPACITY = "opacity";
    1932    String REAL_WIDTH = "real-width";
     33    String REPEAT_IMAGE = "repeat-image";
     34    String REPEAT_IMAGE_ALIGN = "repeat-image-align";
     35    String REPEAT_IMAGE_HEIGHT = "repeat-image-height";
     36    String REPEAT_IMAGE_OFFSET = "repeat-image-offset";
     37    String REPEAT_IMAGE_OPACITY = "repeat-image-opacity";
     38    String REPEAT_IMAGE_PHASE = "repeat-image-phase";
     39    String REPEAT_IMAGE_SPACING = "repeat-image-spacing";
     40    String REPEAT_IMAGE_WIDTH = "repeat-image-width";
     41    String TEXT = "text";
     42    String TEXT_ANCHOR_HORIZONTAL = "text-anchor-horizontal";
     43    String TEXT_ANCHOR_VERTICAL = "text-anchor-vertical";
     44    String TEXT_COLOR = "text-color";
     45    String TEXT_HALO_COLOR = "text-halo-color";
     46    String TEXT_HALO_OPACITY = "text-halo-opacity";
     47    String TEXT_HALO_RADIUS = "text-halo-radius";
     48    String TEXT_OFFSET = "text-offset";
     49    String TEXT_OFFSET_X = "text-offset-x";
     50    String TEXT_OFFSET_Y = "text-offset-y";
     51    String TEXT_OPACITY = "text-opacity";
    2052    String TEXT_POSITION = "text-position";
    21     String TEXT = "text";
    2253    String WIDTH = "width";
    2354    String Z_INDEX = "z-index";
    24     String REPEAT_IMAGE = "repeat-image";
    25     String REPEAT_IMAGE_OFFSET = "repeat-image-offset";
    26     String REPEAT_IMAGE_SPACING = "repeat-image-spacing";
    27     String REPEAT_IMAGE_PHASE = "repeat-image-phase";
    28     String REPEAT_IMAGE_ALIGN = "repeat-image-align";
    2955
    30     int ICON_IMAGE_IDX = 0;
    31     int ICON_WIDTH_IDX = 1;
    32     int ICON_HEIGHT_IDX = 2;
    33     int ICON_OPACITY_IDX = 3;
    34     int ICON_OFFSET_X_IDX = 4;
    35     int ICON_OFFSET_Y_IDX = 5;
    3656}
  • trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java

    r7402 r8087  
    127127        float xOffset = 0;
    128128        float yOffset = 0;
    129         float[] offset = c.get("text-offset", null, float[].class);
     129        float[] offset = c.get(TEXT_OFFSET, null, float[].class);
    130130        if (offset != null) {
    131131            if (offset.length == 1) {
     
    136136            }
    137137        }
    138         xOffset = c.get("text-offset-x", xOffset, Float.class);
    139         yOffset = c.get("text-offset-y", yOffset, Float.class);
    140 
    141         Color color = c.get("text-color", defaultTextColor, Color.class);
    142         float alpha = c.get("text-opacity", 1f, Float.class);
     138        xOffset = c.get(TEXT_OFFSET_X, xOffset, Float.class);
     139        yOffset = c.get(TEXT_OFFSET_Y, yOffset, Float.class);
     140
     141        Color color = c.get(TEXT_COLOR, defaultTextColor, Color.class);
     142        float alpha = c.get(TEXT_OPACITY, 1f, Float.class);
    143143        color = new Color(color.getRed(), color.getGreen(),
    144144                color.getBlue(), Utils.color_float2int(alpha));
    145145
    146         Float haloRadius = c.get("text-halo-radius", null, Float.class);
     146        Float haloRadius = c.get(TEXT_HALO_RADIUS, null, Float.class);
    147147        if (haloRadius != null && haloRadius <= 0) {
    148148            haloRadius = null;
     
    150150        Color haloColor = null;
    151151        if (haloRadius != null) {
    152             haloColor = c.get("text-halo-color", Utils.complement(color), Color.class);
    153             float haloAlpha = c.get("text-halo-opacity", 1f, Float.class);
     152            haloColor = c.get(TEXT_HALO_COLOR, Utils.complement(color), Color.class);
     153            float haloAlpha = c.get(TEXT_HALO_OPACITY, 1f, Float.class);
    154154            haloColor = new Color(haloColor.getRed(), haloColor.getGreen(),
    155155                    haloColor.getBlue(), Utils.color_float2int(haloAlpha));
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj

    r8086 r8087  
    3838 * (a) the preprocessor and (b) the main mapcss parser.
    3939 *
    40  * The preprocessor handles @media syntax. Basically this allows
    41  * to write one style for different versions of JOSM (or different editors).
    42  * When the @media condition is not fulfilled, it should simply skip over
     40 * The preprocessor handles @supports and @media syntax (@media is deprecated).
     41 * Basically this allows to write one style for different versions of JOSM (or different editors).
     42 * When the @supports condition is not fulfilled, it should simply skip over
    4343 * the whole section and not attempt to parse the possibly unknown
    4444 * grammar. It preserves whitespace and comments, in order to keep the
     
    100100{
    101101    < PP_AND: "and" >
     102|   < PP_OR: "or" >
    102103|   < PP_NOT: "not" >
     104|   < PP_SUPPORTS: "@supports" >
    103105|   < PP_MEDIA: "@media" >
    104106|   < PP_NEWLINECHAR: "\n" | "\r" | "\f" >
     
    244246{
    245247    (
    246         (t=<PP_AND> | t=<PP_NOT> | t=<UINT> | t=<STRING> | t=<REGEX> | t=<LPAR> | t=<RPAR> | t=<COMMA> | t=<COLON> | t=<IDENT> | t=<PP_SOMETHING_ELSE>) { if (write) sb.append(t.image); }
     248        (t=<PP_AND> | t=<PP_OR> | t=<PP_NOT> | t=<UINT> | t=<STRING> | t=<REGEX> | t=<LPAR> | t=<RPAR> | t=<COMMA> | t=<COLON> | t=<IDENT> | t=<PP_SOMETHING_ELSE>) { if (write) sb.append(t.image); }
    247249        |
    248250            pp_w1()
     251        |
     252            pp_supports(!write)
    249253        |
    250254            pp_media(!write)
     
    254258}
    255259
     260/**
     261 * Parses an @supports rule.
     262 *
     263 * @param ignore if the content of this rule should be ignored
     264 * (because we are already inside a @supports block that didn't pass)
     265 */
     266void pp_supports(boolean ignore):
     267{
     268    boolean pass;
     269}
     270{
     271    <PP_SUPPORTS> pp_w()
     272    pass=pp_supports_condition()
     273    <LBRACE>
     274    pp_black_box(pass && !ignore)
     275    <RBRACE>
     276}
     277
     278/**
     279 * Parses the condition of the @supports rule.
     280 *
     281 * Unlike other parsing rules, grabs trailing whitespace.
     282 * @return true, if the condition is fulfilled
     283 */
     284boolean pp_supports_condition():
     285{
     286    boolean pass;
     287    boolean q;
     288}
     289{
     290    (
     291        <PP_NOT> pp_w() q=pp_supports_condition_in_parens() { pass = !q; } pp_w()
     292    |
     293        LOOKAHEAD(pp_supports_condition_in_parens() pp_w() <PP_AND>)
     294        pass=pp_supports_condition_in_parens() pp_w()
     295        ( <PP_AND> pp_w() q=pp_supports_condition_in_parens() { pass = pass && q; } pp_w() )+
     296    |
     297        LOOKAHEAD(pp_supports_condition_in_parens() pp_w() <PP_OR>)
     298        pass=pp_supports_condition_in_parens() pp_w()
     299        ( <PP_OR> pp_w() q=pp_supports_condition_in_parens() { pass = pass || q; } pp_w() )+
     300    |
     301        pass=pp_supports_condition_in_parens() pp_w()
     302    )
     303    { return pass; }
     304}
     305
     306/**
     307 * Parses something in parenthesis inside the condition of the @supports rule.
     308 *
     309 * @return true, if the condition is fulfilled
     310 */
     311boolean pp_supports_condition_in_parens():
     312{
     313    boolean pass;
     314}
     315{
     316    (
     317        LOOKAHEAD(pp_supports_declaration_condition())
     318        pass=pp_supports_declaration_condition()
     319    |
     320        <LPAR> pp_w() pass=pp_supports_condition() <RPAR>
     321    )
     322    { return pass; }
     323}
     324
     325/**
     326 * Parse an @supports declaration condition, e.&nbsp;g. a single (key:value) or (key) statement.
     327 *
     328 * The parsing rule {@link #literal()} from the main mapcss parser is reused here.
     329 *
     330 * @return true if the condition is fulfilled
     331 */
     332boolean pp_supports_declaration_condition():
     333{
     334    Token t;
     335    String feature;
     336    Object val = null;
     337}
     338{
     339    <LPAR> pp_w() t=<IDENT> { feature = t.image; } pp_w() ( <COLON> pp_w() val=literal() )? <RPAR>
     340    { return this.sheet.evalSupportsDeclCondition(feature, val); }
     341}
     342
     343// deprecated
    256344void pp_media(boolean ignore):
    257345{
     
    270358}
    271359
     360// deprecated
    272361boolean pp_media_query():
    273362{
     
    302391 * @return true if the condition is fulfilled
    303392 */
     393// deprecated
    304394boolean pp_media_expression():
    305395{
     
    310400{
    311401    <LPAR> pp_w() t=<IDENT> { feature = t.image; } pp_w() ( <COLON> pp_w() val=literal() )? <RPAR>
    312     { return this.sheet.evalMediaExpression(feature, val); }
     402    { return this.sheet.evalSupportsDeclCondition(feature, val); }
    313403}
    314404
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java

    r8086 r8087  
    99import java.io.IOException;
    1010import java.io.InputStream;
     11import java.lang.reflect.Field;
    1112import java.nio.charset.StandardCharsets;
    1213import java.text.MessageFormat;
     
    3334import org.openstreetmap.josm.gui.mappaint.Cascade;
    3435import org.openstreetmap.josm.gui.mappaint.Environment;
     36import org.openstreetmap.josm.gui.mappaint.LineElemStyle;
    3537import org.openstreetmap.josm.gui.mappaint.MultiCascade;
    3638import org.openstreetmap.josm.gui.mappaint.Range;
     39import org.openstreetmap.josm.gui.mappaint.StyleKeys;
    3740import org.openstreetmap.josm.gui.mappaint.StyleSetting;
    3841import org.openstreetmap.josm.gui.mappaint.StyleSetting.BooleanStyleSetting;
     
    8184     */
    8285    public final static ReadWriteLock STYLE_SOURCE_LOCK = new ReentrantReadWriteLock();
     86
     87    /**
     88     * Set of all supported MapCSS keys.
     89     */
     90    public static final Set<String> SUPPORTED_KEYS = new HashSet<>();
     91    static {
     92        Field[] declaredFields = StyleKeys.class.getDeclaredFields();
     93        for (Field f : declaredFields) {
     94            try {
     95                SUPPORTED_KEYS.add((String) f.get(null));
     96                if (!f.getName().toLowerCase().replace("_", "-").equals(f.get(null))) {
     97                    throw new RuntimeException(f.getName());
     98                }
     99            } catch (IllegalArgumentException | IllegalAccessException ex) {
     100                throw new RuntimeException(ex);
     101            }
     102        }
     103        for (LineElemStyle.LineType lt : LineElemStyle.LineType.values()) {
     104            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.COLOR);
     105            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.DASHES);
     106            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.DASHES_BACKGROUND_COLOR);
     107            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.DASHES_BACKGROUND_OPACITY);
     108            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.DASHES_OFFSET);
     109            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.LINECAP);
     110            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.LINEJOIN);
     111            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.MITERLIMIT);
     112            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.OFFSET);
     113            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.OPACITY);
     114            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.REAL_WIDTH);
     115            SUPPORTED_KEYS.add(lt.prefix + StyleKeys.WIDTH);
     116        }
     117    }
    83118
    84119    /**
     
    484519    }
    485520
    486     public boolean evalMediaExpression(String feature, Object val) {
     521    public boolean evalSupportsDeclCondition(String feature, Object val) {
    487522        if (feature == null) return false;
     523        if (SUPPORTED_KEYS.contains(feature)) return true;
    488524        switch (feature) {
    489525            case "user-agent":
Note: See TracChangeset for help on using the changeset viewer.