/*
 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package build.tools.generatenimbus;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


/**
 * PainterGenerator - Class for generating Painter class java source from a Canvas
 *
 * Following in the general theory that is used to generate a Painter file.
 *
 * Each Painter file represents a Region. So there is one painter file per region. In
 * skin.laf we support Icon subregions, which are really just hacked versions of the
 * parent region.
 *
 * In order to generate the most compact and efficient bytecode possible for the
 * Painters, we actually perform the generation sequence in two steps. The first
 * step is the analysis phase, where we walk through the SynthModel for the region
 * and discover commonality among the different states in the region. For example,
 * do they have common paths? Do they have common colors? Gradients? Is the painting
 * code for the different states identical other than for colors?
 *
 * We gather this information up. On the second pass, we use this data to determine the
 * methods that need to be generated, and the class variables that need to be generated.
 * We try to keep the actual bytecode count as small as possible so that we may reduce
 * the overall size of the look and feel significantly.
 *
 * @author  Richard Bair
 * @author  Jasper Potts
 */
public class PainterGenerator {
    //a handful of counters, incremented whenever the associated object type is encounted.
    //These counters form the basis of the field and method suffixes.
    //These are all 1 based, because I felt like it :-)
    private int colorCounter = 1;
    private int gradientCounter = 1;
    private int radialCounter = 1;
    private int pathCounter = 1;
    private int rectCounter = 1;
    private int roundRectCounter = 1;
    private int ellipseCounter = 1;

    private int stateTypeCounter = 1;

    //during the first pass, we will construct these maps
    private Map<String, String> colors = new HashMap<String, String>();
    /**
     * Code=>method name.
     */
    private Map<String, String> methods = new HashMap<String, String>();

    //these variables hold the generated code
    /**
     * The source code in this variable will be used to define the various state types
     */
    private StringBuilder stateTypeCode = new StringBuilder();
    /**
     * The source code in this variable will be used to define the switch statement for painting
     */
    private StringBuilder switchCode = new StringBuilder();
    /**
     * The source code in this variable will be used to define the methods for painting each state
     */
    private StringBuilder paintingCode = new StringBuilder();
    /**
     * The source code in this variable will be used to add getExtendedCacheKeys
     * implementation if needed.
     */
    private StringBuilder getExtendedCacheKeysCode = new StringBuilder();
    /**
     * The source code in this variable will be used to define the methods for decoding gradients
     * and shapes.
     */
    private StringBuilder gradientsCode = new StringBuilder();
    private StringBuilder colorCode = new StringBuilder();
    private StringBuilder shapesCode = new StringBuilder();
    /**
     * Map of component colors keyed by state constant name
     */
    private Map<String, List<ComponentColor>> componentColorsMap =
            new LinkedHashMap<String, List<ComponentColor>>();
    /**
     * For the current state the list of all component colors used by this
     * painter, the index in this list is also the index in the runtime array
     * of defaults and keys.
     */
    private List<ComponentColor> componentColors = null;

    PainterGenerator(UIRegion r) {
        generate(r);
    }

    private void generate(UIRegion r) {
        for (UIState state : r.getBackgroundStates()) {
            Canvas canvas = state.getCanvas();
            String type = (r instanceof UIIconRegion ? r.getKey() : "Background");
            generate(state, canvas, type);
        }
        for (UIState state : r.getForegroundStates()) {
            Canvas canvas = state.getCanvas();
            generate(state, canvas, "Foreground");
        }
        for (UIState state : r.getBorderStates()) {
            Canvas canvas = state.getCanvas();
            generate(state, canvas, "Border");
        }
        //now check for any uiIconRegions, since these are collapsed together.
        for (UIRegion sub : r.getSubRegions()) {
            if (sub instanceof UIIconRegion) {
                generate(sub);
            }
        }
        //generate all the code for component colors
        if (!componentColorsMap.isEmpty()) {
            getExtendedCacheKeysCode
                    .append("    protected Object[] getExtendedCacheKeys(JComponent c) {\n")
                    .append("        Object[] extendedCacheKeys = null;\n")
                    .append("        switch(state) {\n");
            for (Map.Entry<String, List<ComponentColor>> entry : componentColorsMap.entrySet()) {
                getExtendedCacheKeysCode
                    .append("            case ")
                    .append(entry.getKey()).append(":\n")
                    .append("                extendedCacheKeys = new Object[] {\n");
                for (int i=0; i<entry.getValue().size(); i++) {
                    ComponentColor cc = entry.getValue().get(i);
                    cc.write(getExtendedCacheKeysCode);
                    if (i + 1 < entry.getValue().size()) {
                        getExtendedCacheKeysCode.append("),\n");
                    } else {
                        getExtendedCacheKeysCode.append(")");
                    }
                }
                getExtendedCacheKeysCode.append("};\n")
                    .append("                break;\n");
            }
            getExtendedCacheKeysCode
                    .append("        }\n")
                    .append("        return extendedCacheKeys;\n")
                    .append("    }");
        }
    }

    //type is background, foreground, border, upArrowIcon, etc.
    private void generate(UIState state, Canvas canvas, String type) {
        String states = state.getStateKeys();
        String stateType = Utils.statesToConstantName(type + "_" + states);
        String paintMethodName = "paint" + type + Utils.statesToClassName(states);
        //create new array for component colors for this state
        componentColors = new ArrayList<ComponentColor>();

        stateTypeCode.append("    static final int ").append(stateType).append(" = ").append(stateTypeCounter++).append(";\n");

        if (canvas.isBlank()) {
            return;
        }

        switchCode.append("            case ").append(stateType).append(": ").append(paintMethodName).append("(g); break;\n");
        paintingCode.append("    private void ").append(paintMethodName).append("(Graphics2D g) {\n");

        //start by setting up common info needed to encode the control points
        Insets in = canvas.getStretchingInsets();
        float a = in.left;
        float b = canvas.getSize().width - in.right;
        float c = in.top;
        float d = canvas.getSize().height - in.bottom;
        float width = canvas.getSize().width;
        float height = canvas.getSize().height;
        float cw = b - a;
        float ch = d - c;

        Layer[] layers = canvas.getLayers().toArray(new Layer[0]);
        for (int index=layers.length-1; index >= 0; index--) {
            Layer layer = layers[index];

            //shapes must be painted in reverse order
            List<Shape> shapes = layer.getShapes();
            for (int i=shapes.size()-1; i>=0; i--) {
                Shape shape = shapes.get(i);
                Paint paint = shape.getPaint();

                /*
                    We attempt to write the minimal number of bytecodes as possible when
                    generating code. Due to the inherit complexities in determining what
                    is extraneous, we use the following system:

                    We first generate the code for the shape. Then, we check to see if
                    this shape has already been generated. If so, then we defer to an
                    existing method. If not, then we will create a new methods, stick
                    the code in it, and refer to that method.
                */

                String shapeMethodName = null; // will contain the name of the method which creates the shape
                String shapeVariable = null; // will be one of rect, roundRect, ellipse, or path.
                String shapeMethodBody = null;

                if (shape instanceof Rectangle) {
                    Rectangle rshape = (Rectangle) shape;
                    float x1 = encode((float)rshape.getX1(), a, b, width);
                    float y1 = encode((float)rshape.getY1(), c, d, height);
                    float x2 = encode((float)rshape.getX2(), a, b, width);
                    float y2 = encode((float)rshape.getY2(), c, d, height);
                    if (rshape.isRounded()) {
                        //it is a rounded rectangle
                        float rounding = (float)rshape.getRounding();

                        shapeMethodBody =
                                "        roundRect.setRoundRect(" +
                                writeDecodeX(x1) + ", //x\n" +
                                "                               " + writeDecodeY(y1) + ", //y\n" +
                                "                               " + writeDecodeX(x2) + " - " + writeDecodeX(x1) + ", //width\n" +
                                "                               " + writeDecodeY(y2) + " - " + writeDecodeY(y1) + ", //height\n" +
                                "                               " + rounding + "f, " + rounding + "f); //rounding";
                        shapeVariable = "roundRect";
                    } else {
                        shapeMethodBody =
                                "            rect.setRect(" +
                                writeDecodeX(x1) + ", //x\n" +
                                "                         " + writeDecodeY(y1) + ", //y\n" +
                                "                         " + writeDecodeX(x2) + " - " + writeDecodeX(x1) + ", //width\n" +
                                "                         " + writeDecodeY(y2) + " - " + writeDecodeY(y1) + "); //height";
                        shapeVariable = "rect";
                    }
                } else if (shape instanceof Ellipse) {
                    Ellipse eshape = (Ellipse) shape;
                    float x1 = encode((float)eshape.getX1(), a, b, width);
                    float y1 = encode((float)eshape.getY1(), c, d, height);
                    float x2 = encode((float)eshape.getX2(), a, b, width);
                    float y2 = encode((float)eshape.getY2(), c, d, height);
                    shapeMethodBody =
                            "        ellipse.setFrame(" +
                            writeDecodeX(x1) + ", //x\n" +
                            "                         " + writeDecodeY(y1) + ", //y\n" +
                            "                         " + writeDecodeX(x2) + " - " + writeDecodeX(x1) + ", //width\n" +
                            "                         " + writeDecodeY(y2) + " - " + writeDecodeY(y1) + "); //height";
                    shapeVariable = "ellipse";
                } else if (shape instanceof Path) {
                    Path pshape = (Path) shape;
                    List<Point> controlPoints = pshape.getControlPoints();
                    Point first, last;
                    first = last = controlPoints.get(0);
                    StringBuilder buffer = new StringBuilder();
                    buffer.append("        path.reset();\n");
                    buffer.append("        path.moveTo(" + writeDecodeX(encode((float)first.getX(), a, b, width)) + ", " + writeDecodeY(encode((float)first.getY(), c, d, height)) + ");\n");
                    for (int j=1; j<controlPoints.size(); j++) {
                        Point cp = controlPoints.get(j);
                        if (last.isP2Sharp() && cp.isP1Sharp()) {
                            float x = encode((float)cp.getX(), a, b, width);
                            float y = encode((float)cp.getY(), c, d, height);
                            buffer.append("        path.lineTo(" + writeDecodeX(x) + ", " + writeDecodeY(y) + ");\n");
                        } else {
                            float x1 = encode((float)last.getX(), a, b, width);
                            float y1 = encode((float)last.getY(), c, d, height);
                            float x2 = encode((float)cp.getX(), a, b, width);
                            float y2 = encode((float)cp.getY(), c, d, height);
                            buffer.append(
                                    "        path.curveTo(" + writeDecodeBezierX(x1, last.getX(), last.getCp2X()) + ", "
                                                            + writeDecodeBezierY(y1, last.getY(), last.getCp2Y()) + ", "
                                                            + writeDecodeBezierX(x2, cp.getX(), cp.getCp1X()) + ", "
                                                            + writeDecodeBezierY(y2, cp.getY(), cp.getCp1Y()) + ", "
                                                            + writeDecodeX(x2) + ", " + writeDecodeY(y2) + ");\n");
                        }
                        last = cp;
                    }
                    if (last.isP2Sharp() && first.isP1Sharp()) {
                        float x = encode((float)first.getX(), a, b, width);
                        float y = encode((float)first.getY(), c, d, height);
                        buffer.append("        path.lineTo(" + writeDecodeX(x) + ", " + writeDecodeY(y) + ");\n");
                    } else {
                        float x1 = encode((float)last.getX(), a, b, width);
                        float y1 = encode((float)last.getY(), c, d, height);
                        float x2 = encode((float)first.getX(), a, b, width);
                        float y2 = encode((float)first.getY(), c, d, height);
                        buffer.append(
                                "        path.curveTo(" + writeDecodeBezierX(x1, last.getX(), last.getCp2X()) + ", "
                                                        + writeDecodeBezierY(y1, last.getY(), last.getCp2Y()) + ", "
                                                        + writeDecodeBezierX(x2, first.getX(), first.getCp1X()) + ", "
                                                        + writeDecodeBezierY(y2, first.getY(), first.getCp1Y()) + ", "
                                                        + writeDecodeX(x2) + ", " + writeDecodeY(y2) + ");\n");
                    }
                    buffer.append("        path.closePath();");
                    shapeMethodBody = buffer.toString();
                    shapeVariable = "path";
                } else {
                    throw new RuntimeException("Cannot happen unless a new Shape has been defined");
                }

                //now that we have the shape defined in shapeMethodBody, and a shapeVariable name,
                //look to see if such a body has been previously defined.
                shapeMethodName = methods.get(shapeMethodBody);
                String returnType = null;
                if (shapeMethodName == null) {
                    if ("rect".equals(shapeVariable)) {
                        shapeMethodName = "decodeRect" + rectCounter++;
                        returnType = "Rectangle2D";
                    } else if ("roundRect".equals(shapeVariable)) {
                        shapeMethodName = "decodeRoundRect" + roundRectCounter++;
                        returnType = "RoundRectangle2D";
                    } else if ("ellipse".equals(shapeVariable)) {
                        shapeMethodName = "decodeEllipse" + ellipseCounter++;
                        returnType = "Ellipse2D";
                    } else {
                        shapeMethodName = "decodePath" + pathCounter++;
                        returnType = "Path2D";
                    }
                    methods.put(shapeMethodBody, shapeMethodName);

                    //since the method wasn't previously defined, time to define it
                    shapesCode.append("    private ").append(returnType).append(" ").append(shapeMethodName).append("() {\n");
                    shapesCode.append(shapeMethodBody);
                    shapesCode.append("\n");
                    shapesCode.append("        return " + shapeVariable + ";\n");
                    shapesCode.append("    }\n\n");
                }

                //now that the method has been defined, I can go on and decode the
                //paint. After the paint is decoded, I can write the g.fill() method call,
                //using the result of the shapeMethodName. Yay!

//            if (shapeVariable != null) {
            //first, calculate the bounds of the shape being painted and store in variables
                paintingCode.append("        ").append(shapeVariable).append(" = ").append(shapeMethodName).append("();\n");

                if (paint instanceof Matte) {
                    String colorVariable = encodeMatte((Matte)paint);
                    paintingCode.append("        g.setPaint(").append(colorVariable).append(");\n");
                } else if (paint instanceof Gradient) {
                    String gradientMethodName = encodeGradient(shape, (Gradient)paint);
                    paintingCode.append("        g.setPaint(").append(gradientMethodName).append("(").append(shapeVariable).append("));\n");
                } else if (paint instanceof RadialGradient) {
                    String radialMethodName = encodeRadial(shape, (RadialGradient)paint);
                    paintingCode.append("        g.setPaint(").append(radialMethodName).append("(").append(shapeVariable).append("));\n");
                }
                paintingCode.append("        g.fill(").append(shapeVariable).append(");\n");
            }
        }

        paintingCode.append("\n    }\n\n");

        //collect component colors
        if (!componentColors.isEmpty()) {
            componentColorsMap.put(stateType, componentColors);
            componentColors = null;
        }
    }

    private float encode(float x, float a, float b, float w) {
        float r = 0;
        if (x < a) {
            r = (x / a);
        } else if (x > b) {
            r = 2 + ((x - b) / (w - b));
        } else if (x == a && x == b) {
            return 1.5f;
        } else {
            r = 1 + ((x - a) / (b - a));
        }

        if (Float.isNaN(r)) {
            System.err.println("[Error] Encountered NaN: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
            return 0;
        } else if (Float.isInfinite(r)) {
            System.err.println("[Error] Encountered Infinity: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
            return 0;
        } else if (r < 0) {
            System.err.println("[Error] encoded value was less than 0: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
            return 0;
        } else if (r > 3) {
            System.err.println("[Error] encoded value was greater than 3: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
            return 3;
        } else {
            return r;
        }
    }

    private String writeDecodeX(float encodedX) {
        return "decodeX(" + encodedX + "f)";
    }

    private String writeDecodeY(float encodedY) {
        return "decodeY(" + encodedY + "f)";
    }

    /**
     *
     * @param ex encoded x value
     * @param x unencoded x value
     * @param cpx unencoded cpx value
     * @return
     */
    private static String writeDecodeBezierX(double ex, double x, double cpx) {
        return "decodeAnchorX(" + ex + "f, " + (cpx - x) + "f)";
    }

    /**
     *
     * @param ey encoded y value
     * @param y unencoded y value
     * @param cpy unencoded cpy value
     * @return
     */
    private static String writeDecodeBezierY(double ey, double y, double cpy) {
        return "decodeAnchorY(" + ey + "f, " + (cpy - y) + "f)";
    }

    private String encodeMatte(Matte m) {
        String declaration = m.getDeclaration();
        String variableName = colors.get(declaration);
        if (variableName == null) {
            variableName = "color" + colorCounter++;
            colors.put(declaration, variableName);
            colorCode.append(String.format("    private Color %s = %s;\n",
                                           variableName, declaration));
        }
        // handle component colors
        if (m.getComponentPropertyName() != null) {
            ComponentColor cc = m.createComponentColor(variableName);
            int index = componentColors.indexOf(cc);
            if (index == -1) {
                index = componentColors.size();
                componentColors.add(cc);
            }
            return "(Color)componentColors[" + index + "]";
        } else {
            return variableName;
        }
    }

    private String encodeGradient(Shape ps, Gradient g) {
        StringBuilder b = new StringBuilder();
        float x1 = (float)ps.getPaintX1();
        float y1 = (float)ps.getPaintY1();
        float x2 = (float)ps.getPaintX2();
        float y2 = (float)ps.getPaintY2();
        b.append("        return decodeGradient((");
        b.append(x1);
        b.append("f * w) + x, (");
        b.append(y1);
        b.append("f * h) + y, (");
        b.append(x2);
        b.append("f * w) + x, (");
        b.append(y2);
        b.append("f * h) + y,\n");
        encodeGradientColorsAndFractions(g,b);
        b.append(");");

        String methodBody = b.toString();
        String methodName = methods.get(methodBody);
        if (methodName == null) {
            methodName = "decodeGradient" + gradientCounter++;
            gradientsCode.append("    private Paint ").append(methodName).append("(Shape s) {\n");
            gradientsCode.append("        Rectangle2D bounds = s.getBounds2D();\n");
            gradientsCode.append("        float x = (float)bounds.getX();\n");
            gradientsCode.append("        float y = (float)bounds.getY();\n");
            gradientsCode.append("        float w = (float)bounds.getWidth();\n");
            gradientsCode.append("        float h = (float)bounds.getHeight();\n");
            gradientsCode.append(methodBody);
            gradientsCode.append("\n    }\n\n");
            methods.put(methodBody, methodName);
        }
        return methodName;
    }

    /**
     * Takes a abstract gradient and creates the code for the fractions float
     * array and the colors array that can be used in the constructors of linear
     * and radial gradients.
     *
     * @param g The abstract gradient to get stops from
     * @param b Append code string of the form "new float[]{...},
     *          new Color[]{...}" to this StringBuilder
     */
    private void encodeGradientColorsAndFractions(AbstractGradient g,
                                                    StringBuilder b) {
        List<GradientStop> stops = g.getStops();
        // there are stops.size() number of main stops. Between each is a
        // fractional stop. Thus, there are: stops.size() + stops.size() - 1
        // number of fractions and colors.
        float[] fractions = new float[stops.size() + stops.size() - 1];
        String[] colors = new String[fractions.length];
        //for each stop, create the stop and it's associated fraction
        int index = 0; // the index into fractions and colors
        for (int i = 0; i < stops.size(); i++) {
            GradientStop s = stops.get(i);
            //copy over the stop's data
            colors[index] = encodeMatte(s.getColor());
            fractions[index] = s.getPosition();

            //If this isn't the last stop, then add in the fraction
            if (index < fractions.length - 1) {
                float f1 = s.getPosition();
                float f2 = stops.get(i + 1).getPosition();
                index++;
                fractions[index] = f1 + (f2 - f1) * s.getMidpoint();
                colors[index] = "decodeColor("+
                        colors[index - 1]+","+
                        encodeMatte(stops.get(i + 1).getColor())+",0.5f)";
            }
            index++;
        }
        // Check boundry conditions
        for (int i = 1; i < fractions.length; i++) {
            //to avoid an error with LinearGradientPaint where two fractions
            //are identical, bump up the fraction value by a miniscule amount
            //if it is identical to the previous one
            //NOTE: The <= is critical because the previous value may already
            //have been bumped up
            if (fractions[i] <= fractions[i - 1]) {
                fractions[i] = fractions[i - 1] + .000001f;
            }
        }
        //another boundary condition where multiple stops are all at the end. The
        //previous loop bumped all but one of these past 1.0, which is bad.
        //so remove any fractions (and their colors!) that are beyond 1.0
        int outOfBoundsIndex = -1;
        for (int i = 0; i < fractions.length; i++) {
            if (fractions[i] > 1) {
                outOfBoundsIndex = i;
                break;
            }
        }
        if (outOfBoundsIndex >= 0) {
            float[] f = fractions;
            String[] c = colors;
            fractions = new float[outOfBoundsIndex];
            colors = new String[outOfBoundsIndex];
            System.arraycopy(f, 0, fractions, 0, outOfBoundsIndex);
            System.arraycopy(c, 0, colors, 0, outOfBoundsIndex);
        }
        // build string
        b.append("                new float[] { ");
        for (int i = 0; i < fractions.length; i++) {
            if (i>0)b.append(',');
            b.append(fractions[i]);
            b.append('f');
        }
        b.append(" },\n                new Color[] { ");
        for (int i = 0; i < colors.length; i++) {
            if (i>0) b.append(",\n                            ");
            b.append(colors[i]);
        }
        b.append("}");
    }

    private String encodeRadial(Shape ps, RadialGradient g) {
        float centerX1 = (float)ps.getPaintX1();
        float centerY1 = (float)ps.getPaintY1();
        float x2 = (float)ps.getPaintX2();
        float y2 = (float)ps.getPaintY2();
        float radius = (float)Point2D.distance(centerX1, centerY1, x2, y2);
        StringBuilder b = new StringBuilder();

        b.append("        return decodeRadialGradient((");
        b.append(centerX1);
        b.append("f * w) + x, (");
        b.append(centerY1);
        b.append("f * h) + y, ");
        b.append(radius);
        b.append("f,\n");
        encodeGradientColorsAndFractions(g,b);
        b.append(");");

        String methodBody = b.toString();
        String methodName = methods.get(methodBody);
        if (methodName == null) {
            methodName = "decodeRadial" + radialCounter++;
            gradientsCode.append("    private Paint ").append(methodName).append("(Shape s) {\n");
            gradientsCode.append("        Rectangle2D bounds = s.getBounds2D();\n");
            gradientsCode.append("        float x = (float)bounds.getX();\n");
            gradientsCode.append("        float y = (float)bounds.getY();\n");
            gradientsCode.append("        float w = (float)bounds.getWidth();\n");
            gradientsCode.append("        float h = (float)bounds.getHeight();\n");
            gradientsCode.append(methodBody);
            gradientsCode.append("\n    }\n\n");
            methods.put(methodBody, methodName);
        }
        return methodName;
    }

    //note that this method is not thread-safe. In fact, none of this class is.
    public static void writePainter(UIRegion r, String painterName) {
        //Need only write out the stuff for this region, don't need to worry about subregions
        //since this method will be called for each of those (and they go in their own file, anyway).
        //The only subregion that we compound into this is the one for icons.
        PainterGenerator gen = new PainterGenerator(r);
        System.out.println("Generating source file: " + painterName + ".java");

        Map<String, String> variables = Generator.getVariables();
        variables.put("PAINTER_NAME", painterName);
        variables.put("STATIC_DECL", gen.stateTypeCode.toString());
        variables.put("COLORS_DECL", gen.colorCode.toString());
        variables.put("DO_PAINT_SWITCH_BODY", gen.switchCode.toString());
        variables.put("PAINTING_DECL", gen.paintingCode.toString());
        variables.put("GET_EXTENDED_CACHE_KEYS", gen.getExtendedCacheKeysCode.toString());
        variables.put("SHAPES_DECL", gen.shapesCode.toString());
        variables.put("GRADIENTS_DECL", gen.gradientsCode.toString());

        Generator.writeSrcFile("PainterImpl", variables, painterName);
    }
}
