All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cz.vutbr.web.csskit.fn.GenericRadialGradient Maven / Gradle / Ivy

/**
 * GenericRadialGradient.java
 *
 * Created on 17. 5. 2018, 13:14:05 by burgetr
 */
package cz.vutbr.web.csskit.fn;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import cz.vutbr.web.css.CSSFactory;
import cz.vutbr.web.css.Term;
import cz.vutbr.web.css.TermFactory;
import cz.vutbr.web.css.TermIdent;
import cz.vutbr.web.css.TermLength;
import cz.vutbr.web.css.TermLengthOrPercent;
import cz.vutbr.web.css.TermList;
import cz.vutbr.web.css.TermPercent;

/**
 * Base class for both the radial and repating-radial gradient implementations.
 * 
 * @author burgetr
 */
public class GenericRadialGradient extends GenericGradient {
    
    //default property values
    private static final TermPercent DEFAULT_POSITION = CSSFactory.getTermFactory().createPercent(50.0f);
    private static final TermIdent DEFAULT_SHAPE = CSSFactory.getTermFactory().createIdent("ellipse");
    private static final TermIdent CIRCLE_SHAPE = CSSFactory.getTermFactory().createIdent("circle");
    private static final TermIdent DEFAULT_SIZE = CSSFactory.getTermFactory().createIdent("farthest-corner");
    
    private TermIdent shape;
    private TermLengthOrPercent[] size;
    private TermIdent sizeIdent;
    private TermLengthOrPercent[] position;
    
    public TermIdent getShape() {
        return shape;
    }
    
    public TermLengthOrPercent[] getSize() {
        return size;
    }

    public TermIdent getSizeIdent() {
        return sizeIdent;
    }

    public TermLengthOrPercent[] getPosition() {
        return position;
    }

    public TermList setValue(List> value) {
        super.setValue(value);
        List>> args = getSeparatedArgs(DEFAULT_ARG_SEP);
        if (args.size() > 1) {
            int firstStop = 0;
            //check for shape and size
            if (decodeShape(args.get(0))) {
                firstStop = 1;
            } else { //no shape info provided, use defaults
                sizeIdent = DEFAULT_SIZE;
                shape = DEFAULT_SHAPE;
                position = new TermLengthOrPercent[2];
                position[0] = position[1] = DEFAULT_POSITION;
            }
            //check for stops
            loadColorStops(args, firstStop);
            if (getColorStops() != null)
                setValid(true);
        }
        return this;
    }

    private boolean decodeShape(List> arglist) {
        List> args = new ArrayList<>(arglist);
        //determine the 'at' position
        int atpos = -1;
        for (int i = 0; i < args.size(); i++) {
            Term arg = args.get(i);
            if (arg instanceof TermIdent && ((TermIdent) arg).getValue().equalsIgnoreCase("at")) {
                atpos = i;
                break;
            }
        }
        if (atpos != -1) {
            List> posList = args.subList(atpos + 1, args.size());
            if (!decodePosition(posList))
                return false;
            args = args.subList(0, atpos);
        } else { //no position, use the default (center)
            position = new TermLengthOrPercent[2];
            position[0] = position[1] = DEFAULT_POSITION;
        }
        //determine the shape
        boolean isCircle = false;
        for (Iterator> it = args.iterator(); it.hasNext();)
        {
            Term arg = it.next();
            String idval = (arg instanceof TermIdent) ? ((TermIdent) arg).getValue() : null;
            if (idval != null && (idval.equalsIgnoreCase("circle") || idval.equalsIgnoreCase("ellipse"))) {
                shape = (TermIdent) arg;
                isCircle = idval.equalsIgnoreCase("circle");
                it.remove();
                break;
            }
        }
        //determine the size
        if (shape == null) { //shape not given
            if (args.size() == 0) {
                sizeIdent = DEFAULT_SIZE;
                shape = DEFAULT_SHAPE;
            } else if (args.size() == 1) {
                Term arg = args.get(0);
                if (isExtentKeyword(arg)) {
                    sizeIdent = (TermIdent) arg;
                    shape = DEFAULT_SHAPE; //see https://drafts.csswg.org/css-images-3/#radial-gradients
                } else if (arg instanceof TermLength) {
                    size = new TermLengthOrPercent[1];
                    size[0] = (TermLength) arg;
                    shape = CIRCLE_SHAPE;
                } else {
                    return false;
                }
            } else if (args.size() == 2) {
                size = new TermLengthOrPercent[2];
                int i = 0;
                for (Term arg : args) {
                    if (arg instanceof TermLengthOrPercent) {
                        size[i++] = (TermLengthOrPercent) arg;
                    } else {
                        size = null;
                        return false;
                    }
                }
                shape = DEFAULT_SHAPE;
            } else {
                return false;
            }
        } else if (!isCircle) { //ellipse
            if (args.size() == 0) {
                sizeIdent = DEFAULT_SIZE;
            } else if (args.size() == 1) {
                Term arg = args.get(0);
                if (isExtentKeyword(arg)) {
                    sizeIdent = (TermIdent) arg;
                } else {
                    return false;
                }
            } else if (args.size() == 2) {
                size = new TermLengthOrPercent[2];
                int i = 0;
                for (Term arg : args) {
                    if (arg instanceof TermLengthOrPercent) {
                        size[i++] = (TermLengthOrPercent) arg;
                    } else {
                        size = null;
                        return false;
                    }
                }
            } else {
                return false;
            }
        } else { //circle
            if (args.size() == 0) {
                sizeIdent = DEFAULT_SIZE;
            } else if (args.size() == 1) {
                Term arg = args.get(0);
                if (isExtentKeyword(arg)) {
                    sizeIdent = (TermIdent) arg;
                } else if (arg instanceof TermLength) {
                    size = new TermLengthOrPercent[1];
                    size[0] = (TermLength) arg;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
        //parsed ok
        return true;
    }
    
    private boolean decodePosition(List> arglist) {
        if (arglist.size() == 1 || arglist.size() == 2) {
            
            position = new TermLengthOrPercent[2];
            //distribute terms to position
            for (Term term : arglist) {
                if (term instanceof TermIdent || term instanceof TermLengthOrPercent) {
                    storeBackgroundPosition(position, term);
                } else {
                    return false;
                }
            }
            //check validity
            int assigned = 0;
            int valid = 0;
            for (int i = 0; i < 2; i++) {
                if (position[i] == null) {
                    position[i] = DEFAULT_POSITION;
                    valid++;
                } else if (position[i] instanceof TermLengthOrPercent) {
                    assigned++;
                    valid++;
                }
            }
            return (assigned > 0 && valid == 2);
            
        } else {
            return false;
        }
    }
    
    private void storeBackgroundPosition(Term[] storage, Term term) {
        
        if (term instanceof TermIdent) {
            String idval = ((TermIdent) term).getValue();
            TermFactory tf = CSSFactory.getTermFactory();
            if (idval.equalsIgnoreCase("left"))
                setPositionValue(storage, 0, tf.createPercent(0.0f));
            else if (idval.equalsIgnoreCase("right"))
                setPositionValue(storage, 0, tf.createPercent(100.0f));
            else if (idval.equalsIgnoreCase("top"))
                setPositionValue(storage, 1, tf.createPercent(0.0f));
            else if (idval.equalsIgnoreCase("bottom"))
                setPositionValue(storage, 1, tf.createPercent(100.0f));
            else if (idval.equalsIgnoreCase("center"))
                setPositionValue(storage, -1, tf.createPercent(50.0f));
        }
        else
            setPositionValue(storage, -1, term);
    }
    
    private void setPositionValue(Term[] s, int index, Term term) {
        switch (index) {
            case -1: if (s[0] == null) //any position - use the free position
                         s[0] = term;
                     else
                         s[1] = term;
                     break;
            case 0: if (s[0] != null) //if the position is occupied, move the old value
                        s[1] = s[0];
                    s[0] = term;
                    break;
            case 1: if (s[1] != null)
                        s[0] = s[1];
                    s[1] = term;
                    break;
        }
    }
    
    private boolean isExtentKeyword(Term term) {
        if (term instanceof TermIdent) {
            switch (((TermIdent) term).getValue()) {
                case "closest-corner":
                case "closest-side":
                case "farthest-corner":
                case "farthest-side":
                    return true;
                default:
                    return false;
            }
        } else {
            return false;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy