001package armyc2.c5isr.renderer;
002
003import android.graphics.Bitmap;
004import android.graphics.BitmapFactory;
005import android.graphics.Canvas;
006import android.util.Base64;
007
008import com.caverock.androidsvg.SVG;
009import com.caverock.androidsvg.SVGParseException;
010
011import armyc2.c5isr.JavaLineArray.TacticalLines;
012import armyc2.c5isr.JavaTacticalRenderer.TGLight;
013import armyc2.c5isr.RenderMultipoints.clsUtility;
014import armyc2.c5isr.renderer.utilities.Color;
015import armyc2.c5isr.renderer.utilities.ErrorLogger;
016import armyc2.c5isr.renderer.utilities.SymbolID;
017
018/**
019 * Created by michael.spinelli on 8/23/2017.
020 */
021public class PatternFillRenderer {
022    private static final String duriBeachSlopeModerate = "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeBAMAAADJHrORAAAAJ1BMVEUAAADJycnLy8vMzMzNzc3Nzc3Ly8vMzMzNzc3Ly8vMzMzMzMz///8wQwFSAAAAC3RSTlMAISJkZWZn9PT19frFp7oAAAABYktHRAyBs1FjAAAAN0lEQVQY02NgGJKAKVQAhW+xsgVFunv3DmQFbKt37wpA4rPO3r3dAY96Bo+ZzSjmM7oIDM2AAgCrggxuTOFUWwAAAABJRU5ErkJggg==";
023    private static final String duriBeachSlopeSteep = "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeBAMAAADJHrORAAAAJ1BMVEUAAADJycnLy8vMzMzNzc3Nzc3Ly8vMzMzNzc3Ly8vMzMzMzMz///8wQwFSAAAAC3RSTlMAISJkZWZn9PT19frFp7oAAAABYktHRAyBs1FjAAAAN0lEQVQY02NgGJKAKVQAhW+xsgVFunv3DmQFbKt37wpA4rPO3r3dAY96Bo+ZzSjmM7oIDM2AAgCrggxuTOFUWwAAAABJRU5ErkJggg==";
024    private static final String duriFoulGround = "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAABwlBMVEUAAAAAAACAgICqqqqAgICZmZmAgICSkpKOjo6AgICJiYmAgICIiIiHh4eGhoaAgICAgICFhYWFhYWEhISAgICAgICAgICAgICAgICAgICAgICAgICAgICCgoKAgICCgoKAgICAgICCgoKCgoKAgICAgICAgICBgYGAgICBgYGAgICAgICBgYGAgICBgYGBgYGBgYGAgICBgYGBgYGAgICBgYGBgYGBgYGAgICBgYGBgYGCgoKBgYGCgoKBgYGCgoKBgYGAgICBgYF/f3+AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIB/f3+AgICAgICAgICBgYGAgICAgICBgYGAgICAgICAgIB/f3+AgICBgYGAgICAgICBgYGAgICBgYGBgYGAgICBgYGAgICAgICAgICBgYF/f3+AgICAgICBgYF/f3+AgICAgICBgYF/f3+AgICAgICBgYF/f3+AgICAgICBgYF/f3+AgICAgICBgYGAgICAgICBgYF/f3+AgICAgICBgYF/f3+AgID///+d1uhFAAAAk3RSTlMAAQIDBAUGBwkKDQ4PERMUFhcZHR4gIiQmKiwuMDM2Nzo8PT9CREhJTk9QVFVWV1tdXl9hZGVna25vcXJ1dnd4e36Ag4WIiYqLkpSVmZqcnp+ipaqvsLS4u72+v8HCxcjJzc7P0dLT19rb3t7f4+Tl5urr7O7v8PDx8fLy8/P09PX19vb39/j4+fn6+vv8/P39/v6q9ZhUAAAAAWJLR0SVCGB6gwAAAsBJREFUeNrt3MdTU1EcxXEEFVCxd1FU7L2iooINsBcUFStYsGMBA4+IGjAPg6CBfP9gF/eCYQe7+5Pz2Z3JJmdyX3JnYE5BgYiIebNjgGc+NQFkyywWWd8NZC/49BngtclPpDYDJLa5sPIrMHrFZJGHAPF8Fw5/A6JdFnsUpgDe+nQLyKUXWyyy5gswctmnDoAPJk/WkRQQ7XRheQqg0WSR2wA/FrlwsBfo3W+ySCdAuw83AVLLLPZwh+mGTx8BOk1+IAd6geReF5b054Amk0UagVzfUhf2JYHvVXbefWXNuA6AjA+PAZKXxl5bEHyR80zGwOr/pEikIioyVfVDsTeYA8YDwOBYirPhFykp8w71AP21LqyIAZrLxhXZ+R6+PgL0lLuwowvoP2ry57AdIFXowsUsEJVb7LEwDdDs0yuA/iKLRfZEQLrahTkDAA9Mnqxro3mPyNYEEJ80WeQdQMofpobfQHeFyUckBrjnUxtAepbFIrsjIH3c/7ZkAFoMvf33/y4ho8CvsdA34X7yIvwinyZ10XqjIioybYvU1HkRQJ8PrUNA4urYa3XH7Hx7lWYA7vv0BCAutvgrsjkBDJxwwf3ZqtXk/eTcEBCtc2FDAhg6a7LI0/wryakMkNhksUfxhCvJI4BMqcUiG7uAwTMuFPUBtJk8WaczQKLShbURMNxgskgLQFziQnUa6NpiscfMNMBzn+4C/JxnsUhFBAzXuzAjCfDS5MmqifMO06re/H9+sOUOwJ+5LlQBsL1AREREREREREREREREREREREREREREpjHt3IVGO3eB0c5daLRzFxrt3AVGO3dB0M6dzSKah1ORKdPOXbC0cxcY7dyFRjt3oT0i2rkLgnbuVERFpkkR7dyFSjt3odHOXWC0cxca7dwFRjt3odHOnYiIiIiIiIiIiIiIiIiIiIiIiATiL9SSl1hXwqRzAAAAAElFTkSuQmCC";
025    private static final String duriKelp = "iVBORw0KGgoAAAANSUhEUgAAAMgAAAD6CAMAAADTNPgKAAACWFBMVEUAAAAAAACAgICqqqqAgICZmZmAgICSkpKAgICOjo6AgICLi4uAgICJiYmAgICIiIiAgICHh4eAgICGhoaAgICGhoaAgICFhYWAgICEhISAgICAgICEhISAgICAgICDg4OHh4eAgICDg4OAgICCgoKAgICCgoKAgICAgICCgoKAgICCgoKAgICCgoKCgoKAgICCgoKAgICCgoKAgICCgoKAgICEhISCgoKAgICBgYGAgICBgYGAgICBgYGAgICBgYGAgICBgYGAgICBgYGBgYGAgICBgYGAgICBgYGAgICBgYGAgICBgYGBgYGAgICBgYGAgICAgICAgICAgICBgYGAgICAgICBgYGAgICAgICBgYGAgICBgYGAgICBgYGCgoKBgYGAgICBgYGAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYGAgICAgICAgICAgICAgICAgICAgICBgYGAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYGAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYGAgICAgICBgYGAgICAgICBgYGAgICAgICAgICAgIB/f3+AgID////WIOTmAAAAxXRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGxweHyAiIyQmJyorLC0uMDEyMzQ1Nzg5Ojs8PT4+P0BBQkVGR0hLTE1OT1FSU1RVVldYWVteX2BkZmhpam5vcHJzdHV2d3h7fH1+gIGChYeIi46RkpSZmpucnZ+goqSlpqeqq62ur7GztLW4ubq7vLy9v8DBwsPExMXGx8nMzdDR0tPU1dfY29zd3t/h4uPk5ebn6Orr7O3u7/Dx8vP09fb29/j4+fr6+/z9/gntg1kAAAABYktHRMeNBUpbAAADR0lEQVR42u3dZ1MTURSH8aVawAb2EgXsWFBRQbErggUL9gpW1CiKBTv2LvZFRbGLKAoClhhEE+L5XC6ZcWy4m3GGzCXz/F4luTeZ/W+5ezZvjqb5ZEJ5nhYQYh0yKTCSLJeXUQERJLhQjgSpfdK08G2erUrWKx2k5OPxjAhfJo53edJVDlIkIjW7Rvh0mbwfrHIS2xrdyFKyqovlzL1SOUjtKzlmwzMR9/k5IebTQg5K1RDFF6XQKQVukafZ3UxnhR2ViuGKJwnK/CRfRVzHJof+e1JEn4tSt0jpHJ2PiRyKHpXrEKncN6WRLC2TNp4pFa/cUF9/NW2kv3NMfCnVcxtedFp539jUsp3pHX8dDp9+4F1DBOfTIv1FndyI8+1XE2tdA/wao5Vd5Fz3H+8GbH5sbHO9viMzsYP3gx455cYHt7dNtQU3vB1ZKrVZYb7snQ9i9+/xiHM6l/5WfgxefdbhPYvePNSvPqwTubOy18/RtrkeKU61qldabXFLXoifz6zZff++Jsat2H3rvTeNe3/CH4PJj4xsM8yiRC8rE9c6ZYqzqO1fxHMttpF1OMOIUmof2NiXIgfOzD5nHEV9mCoxQhZXiCvP1vhgeGbDlVSUMzlK65a8IGfvodOXdV0vflzxwXsUXSenKXM4ku4aS0A/kztP4s63xiZ/q5HfOYsLtqZGK3NjaW+vl+cZFpPGnP5sbHlV4Z6sjLSUsfHx8f1tHSM0pcwqF2e2+ZNK0KQrRoqba5OD1b3P9zghcinGfM7wm0YRsDlG6bJrYY1ULTXfz53zPVK2LFLpsivuulF2dbUool6LY0tbpWOEramVV6kWC8FhkVM91a7mE+6JZ5/F/z5Dn0j1fMWfSubVy4PRFnPSHaL3VjyH1rXC3tpiJdjkkR3hmvLaWYy3yBf3Eq35C7og1SlaIBhXEqcFhlANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwLRvExg5aEShHBpR+O+koRGFWiJpRKEiGlEoiEYUZmhE8Z9oRGG6d2hE0QRoREEjiiZ4RqcRhUpoRKEUGlEohUYUiqERRXNDIwoF/27RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmovvgWPyAz3pI4IAAAAASUVORK5CYII=";
026    private static final String duriRigField = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAZlBMVEUAAAD///+qqqrMzMzV1dW+vr6/v7/BwcG+vr6/v7/AwMDBwcHBwcG/v7/AwMDAwMDBwcG/v7/AwMC/v7/AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMB3wKozAAAAIXRSTlMAAgMFBk9QUlNUVVZXiImKi4yjpKan19jZ2tvc3d7x8/RAdLIxAAAAAWJLR0QB/wIt3gAAAJBJREFUGBntwcsOgjAUBcCDlDciCIICWs7//6QbFtAmt03cmc4gCP6Xqodp26ahUvCUr9wtGXxcOh60Edw6njRwymlI4aAWGt4KspqWErIHLT1kL1omyDQtGjJNyweyJy0jZAMtd8gqWgrI4pmGVcEhoyGBU8uTK9yiGw+aCD7Smbs5gae47Eetx76IEQTBT77LTiffv21oRgAAAABJRU5ErkJggg==";
027    private static final String duriSweptArea = "iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAMAAAAL34HQAAAAq1BMVEUAAAD/AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP//AP////9KmvTxAAAAN3RSTlMAAwQLDA0kJSYnKCorLC4vS0xNTltcXW1ub3BxcnOoqarMzc7P0NHS09TV1uvs7e7x8vP4+fr7bOJr4wAAAAFiS0dEOKAHpdYAAAGLSURBVHja7drrTsIwGMbxgiCKKAdFHBuIMBVh4yTQ+78zjR/Moju0Cdnb6P93BU/WdevbPEoltYPJy/pwWD9P/LZyRH201AmLoOZAqKq/0j/Ew6p0qmaoU8wuZVPd7nSqbU8y1f1RZzj2BZ9VZqrPXF2pVI2tzrFrCu3BUOeayuxHXxfwJFKdRUWx4rpArJEuFAjEWhbHWpSfqq0NXLu4hhIv/cQk1rj0WK8mscLSY8UmsaLSY+1NYr0Ty+lFdPSVd/QDEZjEeig91o1JrFb5P8W5k79qk1X03TwGiozXw6JYA5kRY5af6qkiM/qcb1wcyJTq5Y2vHbmxup897N9JXkJ0MwbrTUeJupimvu0N8Ws379cRJxpUlLxa8JYMNfdduKT80vIew9V+H4dj70oBAAAAAAAAACCJHrIhesjm6CFbPCt6yOZ7kB6yOXrINughn3YN6SF/o4dsgx7yH1hEesg26CFboYd84mMgPeTEiEEP2Qo9ZDv0kC33Iz1kW/SQAQAAAAAAAOCf+AADVeTkR5OAwAAAAABJRU5ErkJggg==";
028    private static final String duriFishTraps = "iVBORw0KGgoAAAANSUhEUgAAAHwAAABoBAMAAADBd4kAAAAAIVBMVEUAAADCwsLFxcXCwsLAwMDAwMDAwMDAwMDAwMDAwMD///+Tgr1MAAAACXRSTlMAFRYZaWrS09eb/mznAAAAAWJLR0QKaND0VgAAAF5JREFUWMPt17EJgEAQRNERrMHYEmzHEi61BZvQbu1AhUW84E16PH54bJIk45zK1q3Ep2Op8KHt8vLy8g877/c1L7ziOI7jeNf81x/2zZw68vLyTh2nDo7jOI53dupcdiT5TbRBKr0AAAAASUVORK5CYII=";
029
030    private static Bitmap patternBeachSlopeModerate = null;
031    private static Bitmap patternBeachSlopeSteep = null;
032    private static Bitmap patternFoulGround = null;
033    private static Bitmap patternKelp = null;
034    private static Bitmap patternRigField = null;
035    private static Bitmap patternSweptArea = null;
036    private static Bitmap patternFishTraps = null;
037
038    /**
039     * @param hatchStyle Direction of hatch lines - constants from clsUtility
040     * @param spacing horizontal spacing between lines
041     * @param strokeWidth width of lines
042     * @param color Color of lines
043     * @return bitmap with one tile of hatch fill
044     */
045    public static Bitmap MakeHatchPatternFill(int hatchStyle, int spacing, int strokeWidth, Color color) {
046        if (hatchStyle == clsUtility.Hatch_Cross) {
047            Bitmap forward = MakeHatchPatternFill(clsUtility.Hatch_ForwardDiagonal, spacing, strokeWidth, color);
048            Bitmap backward = MakeHatchPatternFill(clsUtility.Hatch_BackwardDiagonal, spacing, strokeWidth, color);
049
050            // concat results
051            Bitmap result = Bitmap.createBitmap(spacing, spacing, forward.getConfig());
052            Canvas canvas = new Canvas(result);
053            canvas.drawBitmap(forward, 0, 0, null);
054            canvas.drawBitmap(backward, 0, 0, null);
055            return result;
056        }
057
058        int x1, x2;
059        if (hatchStyle == clsUtility.Hatch_ForwardDiagonal) {
060             x1 = spacing + strokeWidth;
061             x2 = -strokeWidth;
062        } else if (hatchStyle == clsUtility.Hatch_BackwardDiagonal) {
063             x1 = -strokeWidth;
064             x2 = spacing + strokeWidth;
065        } else {
066            return Bitmap.createBitmap(spacing, spacing, Bitmap.Config.ARGB_8888);
067        }
068
069        String colorStr = "#" + color.toHexString().substring(2);
070
071        /*
072        * SVG is a square with 3 diagonal lines going through it. All lines have the same slope x values
073        * The middle line goes through both corners and the other lines are offset in y by +/- boxLength
074        * Each line extends past the box to confirm the line fills each of the 4 corners
075        */
076        final String hatchFillSVGString = "<svg width=\"" + spacing + "\" height=\"" + spacing + "\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" version=\"1.1\">" +
077        "<g class=\"layer\">"+
078                "<title>Layer 1</title>" +
079                "<g id=\"svg_1\">" +
080                "<line id=\"middle_line\" stroke=\"" + colorStr + "\" stroke-width=\"" + strokeWidth + "\" x1=\"" + x1 + "\" x2=\"" + x2 + "\" y1=\"" + (spacing + strokeWidth) + "\" y2=\"" + (-strokeWidth) + "\"/>" +
081                "<line id=\"bottom_line\" stroke=\"" + colorStr + "\" stroke-width=\"" + strokeWidth + "\" x1=\"" + x1 + "\" x2=\"" + x2 + "\" y1=\"" + (spacing * 2 + strokeWidth) + "\" y2=\"" + (spacing - strokeWidth) + "\"/>" +
082                "<line id=\"top_line\" stroke=\"" + colorStr + "\" stroke-width=\"" + strokeWidth + "\" x1=\"" + x1 + "\" x2=\"" + x2 + "\" y1=\"" + strokeWidth + "\" y2=\"" + (-spacing - strokeWidth) + "\"/>" +
083                "</g></g></svg>";
084
085        // Convert SVG string to bitmap
086        Bitmap bm = Bitmap.createBitmap(spacing, spacing, Bitmap.Config.ARGB_8888);
087        SVG mySVG;
088        try {
089            mySVG = SVG.getFromString(hatchFillSVGString);
090        } catch (SVGParseException e) {
091            // Failed to generate SVG return empty bitmap
092            ErrorLogger.LogException("PatternFillRendererD", "MakeHatchPatternFill", e);
093            return bm;
094        }
095        Canvas canvas = new Canvas(bm);
096        mySVG.setDocumentViewBox(0,0, spacing, spacing);
097        mySVG.renderToCanvas(canvas);
098        return bm;
099    }
100
101    public static Bitmap MakeMetocPatternFill(TGLight tg) {
102        switch (tg.get_LineType()) {
103            case TacticalLines.BEACH_SLOPE_MODERATE:
104                if (patternBeachSlopeModerate == null)
105                    patternBeachSlopeModerate = LoadBMPFromDataURL(duriBeachSlopeModerate);
106                return patternBeachSlopeModerate;
107            case TacticalLines.BEACH_SLOPE_STEEP:
108                if (patternBeachSlopeSteep == null)
109                    patternBeachSlopeSteep = LoadBMPFromDataURL(duriBeachSlopeSteep);
110                return patternBeachSlopeSteep;
111            case TacticalLines.FOUL_GROUND:
112                if (patternFoulGround == null)
113                    patternFoulGround = LoadBMPFromDataURL(duriFoulGround);
114                return patternFoulGround;
115            case TacticalLines.KELP:
116                if (patternKelp == null)
117                    patternKelp = LoadBMPFromDataURL(duriKelp);
118                return patternKelp;
119            case TacticalLines.OIL_RIG_FIELD:
120                if (patternRigField == null)
121                    patternRigField = LoadBMPFromDataURL(duriRigField);
122                return patternRigField;
123            case TacticalLines.SWEPT_AREA:
124                if (patternSweptArea == null)
125                    patternSweptArea = LoadBMPFromDataURL(duriSweptArea);
126                return patternSweptArea;
127            case TacticalLines.FISH_TRAPS:
128                if (patternFishTraps == null)
129                    patternFishTraps = LoadBMPFromDataURL(duriFishTraps);
130                return patternFishTraps;
131            default:
132                return null;
133        }
134    }
135
136    private static Bitmap LoadBMPFromDataURL(String durl)
137    {
138        byte[] decodedString = Base64.decode(durl, Base64.DEFAULT);
139        return BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
140    }
141}