src/main/java/org/fit/layout/cssbox/BoxTransform.java
protected AffineTransform createTransform(ElementBox elem)
    {
        if (elem.isBlock() || elem.isReplaced())
        {
            CSSDecoder dec = new CSSDecoder(elem.getVisualContext());
            Rectangle bounds = elem.getAbsoluteBorderBounds();
            //decode the origin
            int ox, oy;
            CSSProperty.TransformOrigin origin = elem.getStyle().getProperty("transform-origin");
            if (origin == CSSProperty.TransformOrigin.list_values)
            {
                TermList values = elem.getStyle().getValue(TermList.class, "transform-origin");
                ox = dec.getLength((TermLengthOrPercent) values.get(0), false, bounds.width / 2, 0, bounds.width);
                oy = dec.getLength((TermLengthOrPercent) values.get(1), false, bounds.height / 2, 0, bounds.height);
            }
            else
            {
                ox = bounds.width / 2;
                oy = bounds.height / 2;
            }
            ox += bounds.x;
            oy += bounds.y;
            //compute the transformation matrix
            AffineTransform ret = null;
            CSSProperty.Transform trans = elem.getStyle().getProperty("transform");
            if (trans == CSSProperty.Transform.list_values)
            {
                ret = new AffineTransform();
                ret.translate(ox, oy);
                TermList values = elem.getStyle().getValue(TermList.class, "transform");
                for (Term<?> term : values)
                {
                    if (term instanceof TermFunction)
                    {
                        final TermFunction func = (TermFunction) term;
                        final String fname = func.getFunctionName().toLowerCase();
                        if (fname.equals("rotate"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermAngle)
                            {
                                double theta = dec.getAngle((TermAngle) func.get(0));
                                ret.rotate(theta);
                            }
                        }
                        else if (fname.equals("translate"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermLengthOrPercent)
                            {
                                int tx = dec.getLength((TermLengthOrPercent) func.get(0), false, 0, 0, bounds.width);
                                ret.translate(tx, 0.0);
                            }
                            else if (func.size() == 2 && func.get(0) instanceof TermLengthOrPercent && func.get(1) instanceof TermLengthOrPercent)
                            {
                                int tx = dec.getLength((TermLengthOrPercent) func.get(0), false, 0, 0, bounds.width);
                                int ty = dec.getLength((TermLengthOrPercent) func.get(1), false, 0, 0, bounds.height);
                                ret.translate(tx, ty);
                            }
                        }
                        else if (fname.equals("translatex"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermLengthOrPercent)
                            {
                                int tx = dec.getLength((TermLengthOrPercent) func.get(0), false, 0, 0, bounds.width);
                                ret.translate(tx, 0.0);
                            }
                        }
                        else if (fname.equals("translatey"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermLengthOrPercent)
                            {
                                int ty = dec.getLength((TermLengthOrPercent) func.get(0), false, 0, 0, bounds.height);
                                ret.translate(0.0, ty);
                            }
                        }
                        else if (fname.equals("scale"))
                        {
                            if (func.size() == 1 && isNumber(func.get(0)))
                            {
                                float sx = getNumber(func.get(0));
                                ret.scale(sx, sx);
                            }
                            else if (func.size() == 2 && isNumber(func.get(0)) && isNumber(func.get(1)))
                            {
                                float sx = getNumber(func.get(0));
                                float sy = getNumber(func.get(1));
                                ret.scale(sx, sy);
                            }
                        }
                        else if (fname.equals("scalex"))
                        {
                            if (func.size() == 1 && isNumber(func.get(0)))
                            {
                                float sx = getNumber(func.get(0));
                                ret.scale(sx, 1.0);
                            }
                        }
                        else if (fname.equals("scaley"))
                        {
                            if (func.size() == 1 && isNumber(func.get(0)))
                            {
                                float sy = getNumber(func.get(0));
                                ret.scale(1.0, sy);
                            }
                        }
                        else if (fname.equals("skew"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermAngle)
                            {
                                double ax = dec.getAngle((TermAngle) func.get(0));
                                ret.shear(Math.tan(ax), 0.0);
                            }
                            else if (func.size() == 2 && func.get(0) instanceof TermAngle && func.get(1) instanceof TermAngle)
                            {
                                double ax = dec.getAngle((TermAngle) func.get(0));
                                double ay = dec.getAngle((TermAngle) func.get(1));
                                ret.shear(Math.tan(ax), Math.tan(ay));
                            }
                        }
                        else if (fname.equals("skewx"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermAngle)
                            {
                                double ax = dec.getAngle((TermAngle) func.get(0));
                                ret.shear(Math.tan(ax), 0.0);
                            }
                        }
                        else if (fname.equals("skewy"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermAngle)
                            {
                                double ay = dec.getAngle((TermAngle) func.get(0));
                                ret.shear(0.0, Math.tan(ay));
                            }
                        }
                        else if (fname.equals("matrix"))
                        {
                            if (func.size() == 6)
                            {
                                double[] vals = new double[6];
                                boolean typesOk = true;
                                for (int i = 0; i < 6; i++)
                                {
                                    if (isNumber(func.get(i)))
                                        vals[i] = getNumber(func.get(i));
                                    else
                                        typesOk = false;
                                }
                                if (typesOk)
                                {
                                    ret.concatenate(new AffineTransform(vals));
                                }
                            }
                        }
                    }
                }
                ret.translate(-ox, -oy);
            }
            
            return ret;
        }
        else
            return null;
    }
protected AffineTransform createTransform(ElementBox elem)
    {
        if (elem.isBlock() || elem.isReplaced())
        {
            CSSDecoder dec = new CSSDecoder(elem.getVisualContext());
            Rectangle bounds = elem.getAbsoluteBorderBounds();
            //decode the origin
            int ox, oy;
            CSSProperty.TransformOrigin origin = elem.getStyle().getProperty("transform-origin");
            if (origin == CSSProperty.TransformOrigin.list_values)
            {
                TermList values = elem.getStyle().getValue(TermList.class, "transform-origin");
                ox = dec.getLength((TermLengthOrPercent) values.get(0), false, bounds.width / 2, 0, bounds.width);
                oy = dec.getLength((TermLengthOrPercent) values.get(1), false, bounds.height / 2, 0, bounds.height);
            }
            else
            {
                ox = bounds.width / 2;
                oy = bounds.height / 2;
            }
            ox += bounds.x;
            oy += bounds.y;
            //compute the transformation matrix
            AffineTransform ret = null;
            CSSProperty.Transform trans = elem.getStyle().getProperty("transform");
            if (trans == CSSProperty.Transform.list_values)
            {
                ret = new AffineTransform();
                ret.translate(ox, oy);
                TermList values = elem.getStyle().getValue(TermList.class, "transform");
                for (Term<?> term : values)
                {
                    if (term instanceof TermFunction)
                    {
                        final TermFunction func = (TermFunction) term;
                        final String fname = func.getFunctionName().toLowerCase();
                        if (fname.equals("rotate"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermAngle)
                            {
                                double theta = dec.getAngle((TermAngle) func.get(0));
                                ret.rotate(theta);
                            }
                        }
                        else if (fname.equals("translate"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermLengthOrPercent)
                            {
                                int tx = dec.getLength((TermLengthOrPercent) func.get(0), false, 0, 0, bounds.width);
                                ret.translate(tx, 0.0);
                            }
                            else if (func.size() == 2 && func.get(0) instanceof TermLengthOrPercent && func.get(1) instanceof TermLengthOrPercent)
                            {
                                int tx = dec.getLength((TermLengthOrPercent) func.get(0), false, 0, 0, bounds.width);
                                int ty = dec.getLength((TermLengthOrPercent) func.get(1), false, 0, 0, bounds.height);
                                ret.translate(tx, ty);
                            }
                        }
                        else if (fname.equals("translatex"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermLengthOrPercent)
                            {
                                int tx = dec.getLength((TermLengthOrPercent) func.get(0), false, 0, 0, bounds.width);
                                ret.translate(tx, 0.0);
                            }
                        }
                        else if (fname.equals("translatey"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermLengthOrPercent)
                            {
                                int ty = dec.getLength((TermLengthOrPercent) func.get(0), false, 0, 0, bounds.height);
                                ret.translate(0.0, ty);
                            }
                        }
                        else if (fname.equals("scale"))
                        {
                            if (func.size() == 1 && isNumber(func.get(0)))
                            {
                                float sx = getNumber(func.get(0));
                                ret.scale(sx, sx);
                            }
                            else if (func.size() == 2 && isNumber(func.get(0)) && isNumber(func.get(1)))
                            {
                                float sx = getNumber(func.get(0));
                                float sy = getNumber(func.get(1));
                                ret.scale(sx, sy);
                            }
                        }
                        else if (fname.equals("scalex"))
                        {
                            if (func.size() == 1 && isNumber(func.get(0)))
                            {
                                float sx = getNumber(func.get(0));
                                ret.scale(sx, 1.0);
                            }
                        }
                        else if (fname.equals("scaley"))
                        {
                            if (func.size() == 1 && isNumber(func.get(0)))
                            {
                                float sy = getNumber(func.get(0));
                                ret.scale(1.0, sy);
                            }
                        }
                        else if (fname.equals("skew"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermAngle)
                            {
                                double ax = dec.getAngle((TermAngle) func.get(0));
                                ret.shear(Math.tan(ax), 0.0);
                            }
                            else if (func.size() == 2 && func.get(0) instanceof TermAngle && func.get(1) instanceof TermAngle)
                            {
                                double ax = dec.getAngle((TermAngle) func.get(0));
                                double ay = dec.getAngle((TermAngle) func.get(1));
                                ret.shear(Math.tan(ax), Math.tan(ay));
                            }
                        }
                        else if (fname.equals("skewx"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermAngle)
                            {
                                double ax = dec.getAngle((TermAngle) func.get(0));
                                ret.shear(Math.tan(ax), 0.0);
                            }
                        }
                        else if (fname.equals("skewy"))
                        {
                            if (func.size() == 1 && func.get(0) instanceof TermAngle)
                            {
                                double ay = dec.getAngle((TermAngle) func.get(0));
                                ret.shear(0.0, Math.tan(ay));
                            }
                        }
                        else if (fname.equals("matrix"))
                        {
                            if (func.size() == 6)
                            {
                                double[] vals = new double[6];
                                boolean typesOk = true;
                                for (int i = 0; i < 6; i++)
                                {
                                    if (isNumber(func.get(i)))
                                        vals[i] = getNumber(func.get(i));
                                    else
                                        typesOk = false;
                                }
                                if (typesOk)
                                {
                                    ret.concatenate(new AffineTransform(vals));
                                }
                            }
                        }
                    }
                }
                ret.translate(-ox, -oy);
            }
            
            return ret;
        }
        else
            return null;
    }
=========================================================================================================================