alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (RenderClipTest.java)

This example Java source code file (RenderClipTest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

annotatedrenderop, annotatedshapeop, awt, bufferedimage, cubic, event, geometry, image, imagecanvas, linemethod, numberformatexception, path, poly, quad, rect, rectmethod, shape, string, util

The RenderClipTest.java Java example source code

/*
 * Copyright (c) 2008, 2010, 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.
 *
 * 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.
 */

/*
 * @test
 * @bug 6766342
 * @summary Tests clipping invariance for AA rectangle and line primitives
 * @run main RenderClipTest -strict -readfile 6766342.tests
 * @run main RenderClipTest -rectsuite -count 10
 */

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.Vector;
import java.io.*;

public class RenderClipTest {
    public static double randDblCoord() {
        return Math.random()*60 - 10;
    }

    public static float randFltCoord() {
        return (float) randDblCoord();
    }

    public static int randIntCoord() {
        return (int) Math.round(randDblCoord());
    }

    public static int randInt(int n) {
        return ((int) (Math.random() * (n*4))) >> 2;
    }

    static int numtests;
    static int numerrors;
    static int numfillfailures;
    static int numstrokefailures;
    static int maxerr;

    static boolean useAA;
    static boolean strokePure;
    static boolean testFill;
    static boolean testDraw;
    static boolean silent;
    static boolean verbose;
    static boolean strict;
    static boolean showErrors;
    static float lw;
    static double rot;

    static BufferedImage imgref;
    static BufferedImage imgtst;

    static Graphics2D grefclear;
    static Graphics2D gtstclear;
    static Graphics2D grefrender;
    static Graphics2D gtstrender;

    public static abstract class AnnotatedRenderOp {
        public static AnnotatedRenderOp parse(String str) {
            AnnotatedRenderOp ar;
            if (((ar = Cubic.tryparse(str)) != null) ||
                ((ar = Quad.tryparse(str)) != null) ||
                ((ar = Poly.tryparse(str)) != null) ||
                ((ar = Path.tryparse(str)) != null) ||
                ((ar = Rect.tryparse(str)) != null) ||
                ((ar = Line.tryparse(str)) != null) ||
                ((ar = RectMethod.tryparse(str)) != null) ||
                ((ar = LineMethod.tryparse(str)) != null))
            {
                return ar;
            }
            System.err.println("Unable to parse shape: "+str);
            return null;
        }

        public abstract void randomize();

        public abstract void fill(Graphics2D g2d);

        public abstract void draw(Graphics2D g2d);
    }

    public static abstract class AnnotatedShapeOp extends AnnotatedRenderOp {
        public abstract Shape getShape();

        public void fill(Graphics2D g2d) {
            g2d.fill(getShape());
        }

        public void draw(Graphics2D g2d) {
            g2d.draw(getShape());
        }
    }

    public static void usage(String err) {
        if (err != null) {
            System.err.println(err);
        }
        System.err.println("usage: java RenderClipTest "+
                           "[-read[file F]] [-rectsuite] [-fill] [-draw]");
        System.err.println("                           "+
                           "[-aa] [-pure] [-lw N] [-rot N]");
        System.err.println("                           "+
                           "[-rectmethod] [-linemethod] [-rect] [-line]");
        System.err.println("                           "+
                           "[-cubic] [-quad] [-poly] [-path]");
        System.err.println("                           "+
                           "[-silent] [-verbose] [-showerr] [-count N]");
        System.err.println("                           "+
                           "[-strict] [-usage]");
        System.err.println("    -read         Read test data from stdin");
        System.err.println("    -readfile F   Read test data from file F");
        System.err.println("    -rectsuite    Run a suite of rect/line tests");
        System.err.println("    -fill         Test g.fill*(...)");
        System.err.println("    -draw         Test g.draw*(...)");
        System.err.println("    -aa           Use antialiased rendering");
        System.err.println("    -pure         Use STROKE_PURE hint");
        System.err.println("    -lw N         Test line widths of N "+
                           "(default 1.0)");
        System.err.println("    -rot N        Test rotation by N degrees "+
                           "(default 0.0)");
        System.err.println("    -rectmethod   Test fillRect/drawRect methods");
        System.err.println("    -linemethod   Test drawLine method");
        System.err.println("    -rect         Test Rectangle2D shapes");
        System.err.println("    -line         Test Line2D shapes");
        System.err.println("    -cubic        Test CubicCurve2D shapes");
        System.err.println("    -quad         Test QuadCurve2D shapes");
        System.err.println("    -poly         Test Polygon shapes");
        System.err.println("    -path         Test GeneralPath shapes");
        System.err.println("    -silent       Do not print out error curves");
        System.err.println("    -verbose      Print out progress info");
        System.err.println("    -showerr      Display errors on screen");
        System.err.println("    -count N      N tests per shape, then exit "+
                           "(default 1000)");
        System.err.println("    -strict       All failures are important");
        System.err.println("    -usage        Print this help, then exit");
        System.exit((err != null) ? -1 : 0);
    }

    public static void main(String argv[]) {
        boolean readTests = false;
        String readFile = null;
        boolean rectsuite = false;
        int count = 1000;
        lw = 1.0f;
        rot = 0.0;
        Vector<AnnotatedRenderOp> testOps = new Vector();
        for (int i = 0; i < argv.length; i++) {
            String arg = argv[i].toLowerCase();
            if (arg.equals("-aa")) {
                useAA = true;
            } else if (arg.equals("-pure")) {
                strokePure = true;
            } else if (arg.equals("-fill")) {
                testFill = true;
            } else if (arg.equals("-draw")) {
                testDraw = true;
            } else if (arg.equals("-lw")) {
                if (i+1 >= argv.length) {
                    usage("Missing argument: "+argv[i]);
                }
                lw = Float.parseFloat(argv[++i]);
            } else if (arg.equals("-rot")) {
                if (i+1 >= argv.length) {
                    usage("Missing argument: "+argv[i]);
                }
                rot = Double.parseDouble(argv[++i]);
            } else if (arg.equals("-cubic")) {
                testOps.add(new Cubic());
            } else if (arg.equals("-quad")) {
                testOps.add(new Quad());
            } else if (arg.equals("-poly")) {
                testOps.add(new Poly());
            } else if (arg.equals("-path")) {
                testOps.add(new Path());
            } else if (arg.equals("-rect")) {
                testOps.add(new Rect());
            } else if (arg.equals("-line")) {
                testOps.add(new Line());
            } else if (arg.equals("-rectmethod")) {
                testOps.add(new RectMethod());
            } else if (arg.equals("-linemethod")) {
                testOps.add(new LineMethod());
            } else if (arg.equals("-verbose")) {
                verbose = true;
            } else if (arg.equals("-strict")) {
                strict = true;
            } else if (arg.equals("-silent")) {
                silent = true;
            } else if (arg.equals("-showerr")) {
                showErrors = true;
            } else if (arg.equals("-readfile")) {
                if (i+1 >= argv.length) {
                    usage("Missing argument: "+argv[i]);
                }
                readTests = true;
                readFile = argv[++i];
            } else if (arg.equals("-read")) {
                readTests = true;
                readFile = null;
            } else if (arg.equals("-rectsuite")) {
                rectsuite = true;
            } else if (arg.equals("-count")) {
                if (i+1 >= argv.length) {
                    usage("Missing argument: "+argv[i]);
                }
                count = Integer.parseInt(argv[++i]);
            } else if (arg.equals("-usage")) {
                usage(null);
            } else {
                usage("Unknown argument: "+argv[i]);
            }
        }
        if (readTests) {
            if (rectsuite || testDraw || testFill ||
                useAA || strokePure ||
                lw != 1.0f || rot != 0.0 ||
                testOps.size() > 0)
            {
                usage("Should not specify test types with -read options");
            }
        } else if (rectsuite) {
            if (testDraw || testFill ||
                useAA || strokePure ||
                lw != 1.0f || rot != 0.0 ||
                testOps.size() > 0)
            {
                usage("Should not specify test types with -rectsuite option");
            }
        } else {
            if (!testDraw && !testFill) {
                usage("No work: Must specify one or both of "+
                      "-fill or -draw");
            }
            if (testOps.size() == 0) {
                usage("No work: Must specify one or more of "+
                      "-rect[method], -line[method], "+
                      "-cubic, -quad, -poly, or -path");
            }
        }
        initImages();
        if (readTests) {
            try {
                InputStream is;
                if (readFile == null) {
                    is = System.in;
                } else {
                    File f =
                        new File(System.getProperty("test.src", "."),
                                 readFile);
                    is = new FileInputStream(f);
                }
                parseAndRun(is);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else if (rectsuite) {
            runRectSuite(count);
        } else {
            initGCs();
            for (int k = 0; k < testOps.size(); k++) {
                AnnotatedRenderOp ar = testOps.get(k);
                runRandomTests(ar, count);
            }
            disposeGCs();
        }
        grefclear.dispose();
        gtstclear.dispose();
        grefclear = gtstclear = null;
        reportStatistics();
    }

    public static int reportStatistics() {
        String connector = "";
        if (numfillfailures > 0) {
            System.out.print(numfillfailures+" fills ");
            connector = "and ";
        }
        if (numstrokefailures > 0) {
            System.out.print(connector+numstrokefailures+" strokes ");
        }
        int totalfailures = numfillfailures + numstrokefailures;
        if (totalfailures == 0) {
            System.out.print("0 ");
        }
        System.out.println("out of "+numtests+" tests failed...");
        int critical = numerrors;
        if (strict) {
            critical += totalfailures;
        }
        if (critical > 0) {
            throw new RuntimeException(critical+" tests had critical errors");
        }
        System.out.println("No tests had critical errors");
        return (numerrors+totalfailures);
    }

    public static void runRectSuite(int count) {
        AnnotatedRenderOp ops[] = {
            new Rect(),
            new RectMethod(),
            new Line(),
            new LineMethod(),
        };
        // Sometimes different fill algorithms are chosen for
        // thin and wide line modes, make sure we test both...
        float filllinewidths[] = { 0.0f, 2.0f };
        float drawlinewidths[] = { 0.0f, 0.5f, 1.0f,
                                   2.0f, 2.5f,
                                   5.0f, 5.3f };
        double rotations[] = { 0.0, 15.0, 90.0,
                               135.0, 180.0,
                               200.0, 270.0,
                               300.0};
        for (AnnotatedRenderOp ar: ops) {
            for (double r: rotations) {
                rot = r;
                for (int i = 0; i < 8; i++) {
                    float linewidths[];
                    if ((i & 1) == 0) {
                        if ((ar instanceof Line) ||
                            (ar instanceof LineMethod))
                        {
                            continue;
                        }
                        testFill = true;
                        testDraw = false;
                        linewidths = filllinewidths;
                    } else {
                        testFill = false;
                        testDraw = true;
                        linewidths = drawlinewidths;
                    }
                    useAA = ((i & 2) != 0);
                    strokePure = ((i & 4) != 0);
                    for (float w : linewidths) {
                        lw = w;
                        runSuiteTests(ar, count);
                    }
                }
            }
        }
    }

    public static void runSuiteTests(AnnotatedRenderOp ar, int count) {
        if (verbose) {
            System.out.print("Running ");
            System.out.print(testFill ? "Fill " : "Draw ");
            System.out.print(BaseName(ar));
            if (useAA) {
                System.out.print(" AA");
            }
            if (strokePure) {
                System.out.print(" Pure");
            }
            if (lw != 1.0f) {
                System.out.print(" lw="+lw);
            }
            if (rot != 0.0f) {
                System.out.print(" rot="+rot);
            }
            System.out.println();
        }
        initGCs();
        runRandomTests(ar, count);
        disposeGCs();
    }

    public static String BaseName(AnnotatedRenderOp ar) {
        String s = ar.toString();
        int leftparen = s.indexOf('(');
        if (leftparen >= 0) {
            s = s.substring(0, leftparen);
        }
        return s;
    }

    public static void runRandomTests(AnnotatedRenderOp ar, int count) {
        for (int i = 0; i < count; i++) {
            ar.randomize();
            if (testDraw) {
                test(ar, false);
            }
            if (testFill) {
                test(ar, true);
            }
        }
    }

    public static void initImages() {
        imgref = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
        imgtst = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
        grefclear = imgref.createGraphics();
        gtstclear = imgtst.createGraphics();
        grefclear.setColor(Color.white);
        gtstclear.setColor(Color.white);
    }

    public static void initGCs() {
        grefrender = imgref.createGraphics();
        gtstrender = imgtst.createGraphics();
        gtstrender.clipRect(10, 10, 20, 20);
        grefrender.setColor(Color.blue);
        gtstrender.setColor(Color.blue);
        if (lw != 1.0f) {
            BasicStroke bs = new BasicStroke(lw);
            grefrender.setStroke(bs);
            gtstrender.setStroke(bs);
        }
        if (rot != 0.0) {
            double rotrad = Math.toRadians(rot);
            grefrender.rotate(rotrad, 20, 20);
            gtstrender.rotate(rotrad, 20, 20);
        }
        if (strokePure) {
            grefrender.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
                                        RenderingHints.VALUE_STROKE_PURE);
            gtstrender.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
                                        RenderingHints.VALUE_STROKE_PURE);
        }
        if (useAA) {
            grefrender.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                        RenderingHints.VALUE_ANTIALIAS_ON);
            gtstrender.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                        RenderingHints.VALUE_ANTIALIAS_ON);
            maxerr = 1;
        }
    }

    public static void disposeGCs() {
        grefrender.dispose();
        gtstrender.dispose();
        grefrender = gtstrender = null;
    }

    public static void parseAndRun(InputStream in) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String str;
        while ((str = br.readLine()) != null) {
            if (str.startsWith("Stroked ") || str.startsWith("Filled ")) {
                parseTest(str);
                continue;
            }
            if (str.startsWith("Running ")) {
                continue;
            }
            if (str.startsWith("Failed: ")) {
                continue;
            }
            if (str.indexOf(" out of ") > 0 &&
                str.indexOf(" tests failed...") > 0)
            {
                continue;
            }
            if (str.indexOf(" tests had critical errors") > 0) {
                continue;
            }
            System.err.println("Unparseable line: "+str);
        }
    }

    public static void parseTest(String origstr) {
        String str = origstr;
        boolean isfill = false;
        useAA = strokePure = false;
        lw = 1.0f;
        rot = 0.0;
        if (str.startsWith("Stroked ")) {
            str = str.substring(8);
            isfill = false;
        } else if (str.startsWith("Filled ")) {
            str = str.substring(7);
            isfill = true;
        } else {
            System.err.println("Unparseable test line: "+origstr);
        }
        if (str.startsWith("AA ")) {
            str = str.substring(3);
            useAA = true;
        }
        if (str.startsWith("Pure ")) {
            str = str.substring(5);
            strokePure = true;
        }
        if (str.startsWith("Lw=")) {
            int index = str.indexOf(' ', 3);
            if (index > 0) {
                lw = Float.parseFloat(str.substring(3, index));
                str = str.substring(index+1);
            }
        }
        if (str.startsWith("Rot=")) {
            int index = str.indexOf(' ', 4);
            if (index > 0) {
                rot = Double.parseDouble(str.substring(4, index));
                str = str.substring(index+1);
            }
        }
        AnnotatedRenderOp ar = AnnotatedRenderOp.parse(str);
        if (ar != null) {
            initGCs();
            test(ar, isfill);
            disposeGCs();
        } else {
            System.err.println("Unparseable test line: "+origstr);
        }
    }

    public static void test(AnnotatedRenderOp ar, boolean isfill) {
        grefclear.fillRect(0, 0, 40, 40);
        gtstclear.fillRect(0, 0, 40, 40);
        if (isfill) {
            ar.fill(grefrender);
            ar.fill(gtstrender);
        } else {
            ar.draw(grefrender);
            ar.draw(gtstrender);
        }
        check(imgref, imgtst, ar, isfill);
    }

    public static int[] getData(BufferedImage img) {
        Raster r = img.getRaster();
        DataBufferInt dbi = (DataBufferInt) r.getDataBuffer();
        return dbi.getData();
    }

    public static int getScan(BufferedImage img) {
        Raster r = img.getRaster();
        SinglePixelPackedSampleModel sppsm =
            (SinglePixelPackedSampleModel) r.getSampleModel();
        return sppsm.getScanlineStride();
    }

    public static int getOffset(BufferedImage img) {
        Raster r = img.getRaster();
        SinglePixelPackedSampleModel sppsm =
            (SinglePixelPackedSampleModel) r.getSampleModel();
        return sppsm.getOffset(-r.getSampleModelTranslateX(),
                               -r.getSampleModelTranslateY());
    }

    final static int opaque = 0xff000000;
    final static int whitergb = Color.white.getRGB();

    public static final int maxdiff(int rgb1, int rgb2) {
        int maxd = 0;
        for (int i = 0; i < 32; i += 8) {
            int c1 = (rgb1 >> i) & 0xff;
            int c2 = (rgb2 >> i) & 0xff;
            int d = Math.abs(c1-c2);
            if (maxd < d) {
                maxd = d;
            }
        }
        return maxd;
    }

    public static void check(BufferedImage imgref, BufferedImage imgtst,
                             AnnotatedRenderOp ar, boolean wasfill)
    {
        numtests++;
        int dataref[] = getData(imgref);
        int datatst[] = getData(imgtst);
        int scanref = getScan(imgref);
        int scantst = getScan(imgtst);
        int offref = getOffset(imgref);
        int offtst = getOffset(imgtst);

        // We want to check for errors outside the clip at a higher
        // priority than errors involving different pixels touched
        // inside the clip.

        // Check above clip
        if (check(ar, wasfill,
                  null, 0, 0,
                  datatst, scantst, offtst,
                  0, 0, 40, 10))
        {
            return;
        }
        // Check below clip
        if (check(ar, wasfill,
                  null, 0, 0,
                  datatst, scantst, offtst,
                  0, 30, 40, 40))
        {
            return;
        }
        // Check left of clip
        if (check(ar, wasfill,
                  null, 0, 0,
                  datatst, scantst, offtst,
                  0, 10, 10, 30))
        {
            return;
        }
        // Check right of clip
        if (check(ar, wasfill,
                  null, 0, 0,
                  datatst, scantst, offtst,
                  30, 10, 40, 30))
        {
            return;
        }
        // Check inside clip
        check(ar, wasfill,
              dataref, scanref, offref,
              datatst, scantst, offtst,
              10, 10, 30, 30);
    }

    public static boolean check(AnnotatedRenderOp ar, boolean wasfill,
                                int dataref[], int scanref, int offref,
                                int datatst[], int scantst, int offtst,
                                int x0, int y0, int x1, int y1)
    {
        offref += scanref * y0;
        offtst += scantst * y0;
        for (int y = y0; y < y1; y++) {
            for (int x = x0; x < x1; x++) {
                boolean failed;
                String reason;
                int rgbref;
                int rgbtst;

                rgbtst = datatst[offtst+x] | opaque;
                if (dataref == null) {
                    /* Outside of clip, must be white, no error tolerance */
                    rgbref = whitergb;
                    failed = (rgbtst != rgbref);
                    reason = "stray pixel rendered outside of clip";
                } else {
                    /* Inside of clip, check for maxerr delta in components */
                    rgbref = dataref[offref+x] | opaque;
                    failed = (rgbref != rgbtst &&
                              maxdiff(rgbref, rgbtst) > maxerr);
                    reason = "different pixel rendered inside clip";
                }
                if (failed) {
                    if (dataref == null) {
                        numerrors++;
                    }
                    if (wasfill) {
                        numfillfailures++;
                    } else {
                        numstrokefailures++;
                    }
                    if (!silent) {
                        System.out.println("Failed: "+reason+" at "+x+", "+y+
                                           " ["+Integer.toHexString(rgbref)+
                                           " != "+Integer.toHexString(rgbtst)+
                                           "]");
                        System.out.print(wasfill ? "Filled " : "Stroked ");
                        if (useAA) System.out.print("AA ");
                        if (strokePure) System.out.print("Pure ");
                        if (lw != 1) System.out.print("Lw="+lw+" ");
                        if (rot != 0) System.out.print("Rot="+rot+" ");
                        System.out.println(ar);
                    }
                    if (showErrors) {
                        show(imgref, imgtst);
                    }
                    return true;
                }
            }
            offref += scanref;
            offtst += scantst;
        }
        return false;
    }

    static ErrorWindow errw;

    public static void show(BufferedImage imgref, BufferedImage imgtst) {
        ErrorWindow errw = new ErrorWindow();
        errw.setImages(imgref, imgtst);
        errw.setVisible(true);
        errw.waitForHide();
        errw.dispose();
    }

    public static class Cubic extends AnnotatedShapeOp {
        public static Cubic tryparse(String str) {
            str = str.trim();
            if (!str.startsWith("Cubic(")) {
                return null;
            }
            str = str.substring(6);
            double coords[] = new double[8];
            boolean foundparen = false;
            for (int i = 0; i < coords.length; i++) {
                int index = str.indexOf(",");
                if (index < 0) {
                    if (i < coords.length-1) {
                        return null;
                    }
                    index = str.indexOf(")");
                    if (index < 0) {
                        return null;
                    }
                    foundparen = true;
                }
                String num = str.substring(0, index);
                try {
                    coords[i] = Double.parseDouble(num);
                } catch (NumberFormatException nfe) {
                    return null;
                }
                str = str.substring(index+1);
            }
            if (!foundparen || str.length() > 0) {
                return null;
            }
            Cubic c = new Cubic();
            c.cubic.setCurve(coords[0], coords[1],
                             coords[2], coords[3],
                             coords[4], coords[5],
                             coords[6], coords[7]);
            return c;
        }

        private CubicCurve2D cubic = new CubicCurve2D.Double();

        public void randomize() {
            cubic.setCurve(randDblCoord(), randDblCoord(),
                           randDblCoord(), randDblCoord(),
                           randDblCoord(), randDblCoord(),
                           randDblCoord(), randDblCoord());
        }

        public Shape getShape() {
            return cubic;
        }

        public String toString() {
            return ("Cubic("+
                    cubic.getX1()+", "+
                    cubic.getY1()+", "+
                    cubic.getCtrlX1()+", "+
                    cubic.getCtrlY1()+", "+
                    cubic.getCtrlX2()+", "+
                    cubic.getCtrlY2()+", "+
                    cubic.getX2()+", "+
                    cubic.getY2()
                    +")");
        }
    }

    public static class Quad extends AnnotatedShapeOp {
        public static Quad tryparse(String str) {
            str = str.trim();
            if (!str.startsWith("Quad(")) {
                return null;
            }
            str = str.substring(5);
            double coords[] = new double[6];
            boolean foundparen = false;
            for (int i = 0; i < coords.length; i++) {
                int index = str.indexOf(",");
                if (index < 0) {
                    if (i < coords.length-1) {
                        return null;
                    }
                    index = str.indexOf(")");
                    if (index < 0) {
                        return null;
                    }
                    foundparen = true;
                }
                String num = str.substring(0, index);
                try {
                    coords[i] = Double.parseDouble(num);
                } catch (NumberFormatException nfe) {
                    return null;
                }
                str = str.substring(index+1);
            }
            if (!foundparen || str.length() > 0) {
                return null;
            }
            Quad c = new Quad();
            c.quad.setCurve(coords[0], coords[1],
                            coords[2], coords[3],
                            coords[4], coords[5]);
            return c;
        }

        private QuadCurve2D quad = new QuadCurve2D.Double();

        public void randomize() {
            quad.setCurve(randDblCoord(), randDblCoord(),
                          randDblCoord(), randDblCoord(),
                          randDblCoord(), randDblCoord());
        }

        public Shape getShape() {
            return quad;
        }

        public String toString() {
            return ("Quad("+
                    quad.getX1()+", "+
                    quad.getY1()+", "+
                    quad.getCtrlX()+", "+
                    quad.getCtrlY()+", "+
                    quad.getX2()+", "+
                    quad.getY2()
                    +")");
        }
    }

    public static class Poly extends AnnotatedShapeOp {
        public static Poly tryparse(String str) {
            str = str.trim();
            if (!str.startsWith("Poly(")) {
                return null;
            }
            str = str.substring(5);
            Polygon p = new Polygon();
            while (true) {
                int x, y;
                str = str.trim();
                if (str.startsWith(")")) {
                    str = str.substring(1);
                    break;
                }
                if (p.npoints > 0) {
                    if (str.startsWith(",")) {
                        str = str.substring(2).trim();
                    } else {
                        return null;
                    }
                }
                if (str.startsWith("[")) {
                    str = str.substring(1);
                } else {
                    return null;
                }
                int index = str.indexOf(",");
                if (index < 0) {
                    return null;
                }
                String num = str.substring(0, index);
                try {
                    x = Integer.parseInt(num);
                } catch (NumberFormatException nfe) {
                    return null;
                }
                str = str.substring(index+1);
                index = str.indexOf("]");
                if (index < 0) {
                    return null;
                }
                num = str.substring(0, index).trim();
                try {
                    y = Integer.parseInt(num);
                } catch (NumberFormatException nfe) {
                    return null;
                }
                str = str.substring(index+1);
                p.addPoint(x, y);
            }
            if (str.length() > 0) {
                return null;
            }
            if (p.npoints < 3) {
                return null;
            }
            return new Poly(p);
        }

        private Polygon poly;

        public Poly() {
            this.poly = new Polygon();
        }

        private Poly(Polygon p) {
            this.poly = p;
        }

        public void randomize() {
            poly.reset();
            poly.addPoint(randIntCoord(), randIntCoord());
            poly.addPoint(randIntCoord(), randIntCoord());
            poly.addPoint(randIntCoord(), randIntCoord());
            poly.addPoint(randIntCoord(), randIntCoord());
            poly.addPoint(randIntCoord(), randIntCoord());
        }

        public Shape getShape() {
            return poly;
        }

        public String toString() {
            StringBuffer sb = new StringBuffer(100);
            sb.append("Poly(");
            for (int i = 0; i < poly.npoints; i++) {
                if (i != 0) {
                    sb.append(", ");
                }
                sb.append("[");
                sb.append(poly.xpoints[i]);
                sb.append(", ");
                sb.append(poly.ypoints[i]);
                sb.append("]");
            }
            sb.append(")");
            return sb.toString();
        }
    }

    public static class Path extends AnnotatedShapeOp {
        public static Path tryparse(String str) {
            str = str.trim();
            if (!str.startsWith("Path(")) {
                return null;
            }
            str = str.substring(5);
            GeneralPath gp = new GeneralPath();
            float coords[] = new float[6];
            int numsegs = 0;
            while (true) {
                int type;
                int n;
                str = str.trim();
                if (str.startsWith(")")) {
                    str = str.substring(1);
                    break;
                }
                if (str.startsWith("M[")) {
                    type = PathIterator.SEG_MOVETO;
                    n = 2;
                } else if (str.startsWith("L[")) {
                    type = PathIterator.SEG_LINETO;
                    n = 2;
                } else if (str.startsWith("Q[")) {
                    type = PathIterator.SEG_QUADTO;
                    n = 4;
                } else if (str.startsWith("C[")) {
                    type = PathIterator.SEG_CUBICTO;
                    n = 6;
                } else if (str.startsWith("E[")) {
                    type = PathIterator.SEG_CLOSE;
                    n = 0;
                } else {
                    return null;
                }
                str = str.substring(2);
                if (n == 0) {
                    if (str.startsWith("]")) {
                        str = str.substring(1);
                    } else {
                        return null;
                    }
                }
                for (int i = 0; i < n; i++) {
                    int index;
                    if (i < n-1) {
                        index = str.indexOf(",");
                    } else {
                        index = str.indexOf("]");
                    }
                    if (index < 0) {
                        return null;
                    }
                    String num = str.substring(0, index);
                    try {
                        coords[i] = Float.parseFloat(num);
                    } catch (NumberFormatException nfe) {
                        return null;
                    }
                    str = str.substring(index+1).trim();
                }
                switch (type) {
                case PathIterator.SEG_MOVETO:
                    gp.moveTo(coords[0], coords[1]);
                    break;
                case PathIterator.SEG_LINETO:
                    gp.lineTo(coords[0], coords[1]);
                    break;
                case PathIterator.SEG_QUADTO:
                    gp.quadTo(coords[0], coords[1],
                              coords[2], coords[3]);
                    break;
                case PathIterator.SEG_CUBICTO:
                    gp.curveTo(coords[0], coords[1],
                               coords[2], coords[3],
                               coords[4], coords[5]);
                    break;
                case PathIterator.SEG_CLOSE:
                    gp.closePath();
                    break;
                }
                numsegs++;
            }
            if (str.length() > 0) {
                return null;
            }
            if (numsegs < 2) {
                return null;
            }
            return new Path(gp);
        }

        private GeneralPath path;

        public Path() {
            this.path = new GeneralPath();
        }

        private Path(GeneralPath gp) {
            this.path = gp;
        }

        public void randomize() {
            path.reset();
            path.moveTo(randFltCoord(), randFltCoord());
            for (int i = randInt(5)+3; i > 0; --i) {
                switch(randInt(5)) {
                case 0:
                    path.moveTo(randFltCoord(), randFltCoord());
                    break;
                case 1:
                    path.lineTo(randFltCoord(), randFltCoord());
                    break;
                case 2:
                    path.quadTo(randFltCoord(), randFltCoord(),
                                randFltCoord(), randFltCoord());
                    break;
                case 3:
                    path.curveTo(randFltCoord(), randFltCoord(),
                                 randFltCoord(), randFltCoord(),
                                 randFltCoord(), randFltCoord());
                    break;
                case 4:
                    path.closePath();
                    break;
                }
            }
        }

        public Shape getShape() {
            return path;
        }

        public String toString() {
            StringBuffer sb = new StringBuffer(100);
            sb.append("Path(");
            PathIterator pi = path.getPathIterator(null);
            float coords[] = new float[6];
            boolean first = true;
            while (!pi.isDone()) {
                int n;
                char c;
                switch(pi.currentSegment(coords)) {
                case PathIterator.SEG_MOVETO:
                    c = 'M';
                    n = 2;
                    break;
                case PathIterator.SEG_LINETO:
                    c = 'L';
                    n = 2;
                    break;
                case PathIterator.SEG_QUADTO:
                    c = 'Q';
                    n = 4;
                    break;
                case PathIterator.SEG_CUBICTO:
                    c = 'C';
                    n = 6;
                    break;
                case PathIterator.SEG_CLOSE:
                    c = 'E';
                    n = 0;
                    break;
                default:
                    throw new InternalError("Unknown segment!");
                }
                sb.append(c);
                sb.append("[");
                for (int i = 0; i < n; i++) {
                    if (i != 0) {
                        sb.append(",");
                    }
                    sb.append(coords[i]);
                }
                sb.append("]");
                pi.next();
            }
            sb.append(")");
            return sb.toString();
        }
    }

    public static class Rect extends AnnotatedShapeOp {
        public static Rect tryparse(String str) {
            str = str.trim();
            if (!str.startsWith("Rect(")) {
                return null;
            }
            str = str.substring(5);
            double coords[] = new double[4];
            boolean foundparen = false;
            for (int i = 0; i < coords.length; i++) {
                int index = str.indexOf(",");
                if (index < 0) {
                    if (i < coords.length-1) {
                        return null;
                    }
                    index = str.indexOf(")");
                    if (index < 0) {
                        return null;
                    }
                    foundparen = true;
                }
                String num = str.substring(0, index);
                try {
                    coords[i] = Double.parseDouble(num);
                } catch (NumberFormatException nfe) {
                    return null;
                }
                str = str.substring(index+1);
            }
            if (!foundparen || str.length() > 0) {
                return null;
            }
            Rect r = new Rect();
            r.rect.setRect(coords[0], coords[1],
                           coords[2], coords[3]);
            return r;
        }

        private Rectangle2D rect = new Rectangle2D.Double();

        public void randomize() {
            rect.setRect(randDblCoord(), randDblCoord(),
                         randDblCoord(), randDblCoord());
        }

        public Shape getShape() {
            return rect;
        }

        public String toString() {
            return ("Rect("+
                    rect.getX()+", "+
                    rect.getY()+", "+
                    rect.getWidth()+", "+
                    rect.getHeight()
                    +")");
        }
    }

    public static class Line extends AnnotatedShapeOp {
        public static Line tryparse(String str) {
            str = str.trim();
            if (!str.startsWith("Line(")) {
                return null;
            }
            str = str.substring(5);
            double coords[] = new double[4];
            boolean foundparen = false;
            for (int i = 0; i < coords.length; i++) {
                int index = str.indexOf(",");
                if (index < 0) {
                    if (i < coords.length-1) {
                        return null;
                    }
                    index = str.indexOf(")");
                    if (index < 0) {
                        return null;
                    }
                    foundparen = true;
                }
                String num = str.substring(0, index);
                try {
                    coords[i] = Double.parseDouble(num);
                } catch (NumberFormatException nfe) {
                    return null;
                }
                str = str.substring(index+1);
            }
            if (!foundparen || str.length() > 0) {
                return null;
            }
            Line l = new Line();
            l.line.setLine(coords[0], coords[1],
                           coords[2], coords[3]);
            return l;
        }

        private Line2D line = new Line2D.Double();

        public void randomize() {
            line.setLine(randDblCoord(), randDblCoord(),
                         randDblCoord(), randDblCoord());
        }

        public Shape getShape() {
            return line;
        }

        public String toString() {
            return ("Line("+
                    line.getX1()+", "+
                    line.getY1()+", "+
                    line.getX2()+", "+
                    line.getY2()
                    +")");
        }
    }

    public static class RectMethod extends AnnotatedRenderOp {
        public static RectMethod tryparse(String str) {
            str = str.trim();
            if (!str.startsWith("RectMethod(")) {
                return null;
            }
            str = str.substring(11);
            int coords[] = new int[4];
            boolean foundparen = false;
            for (int i = 0; i < coords.length; i++) {
                int index = str.indexOf(",");
                if (index < 0) {
                    if (i < coords.length-1) {
                        return null;
                    }
                    index = str.indexOf(")");
                    if (index < 0) {
                        return null;
                    }
                    foundparen = true;
                }
                String num = str.substring(0, index).trim();
                try {
                    coords[i] = Integer.parseInt(num);
                } catch (NumberFormatException nfe) {
                    return null;
                }
                str = str.substring(index+1);
            }
            if (!foundparen || str.length() > 0) {
                return null;
            }
            RectMethod rm = new RectMethod();
            rm.rect.setBounds(coords[0], coords[1],
                              coords[2], coords[3]);
            return rm;
        }

        private Rectangle rect = new Rectangle();

        public void randomize() {
            rect.setBounds(randIntCoord(), randIntCoord(),
                           randIntCoord(), randIntCoord());
        }

        public void fill(Graphics2D g2d) {
            g2d.fillRect(rect.x, rect.y, rect.width, rect.height);
        }

        public void draw(Graphics2D g2d) {
            g2d.drawRect(rect.x, rect.y, rect.width, rect.height);
        }

        public String toString() {
            return ("RectMethod("+
                    rect.x+", "+
                    rect.y+", "+
                    rect.width+", "+
                    rect.height
                    +")");
        }
    }

    public static class LineMethod extends AnnotatedRenderOp {
        public static LineMethod tryparse(String str) {
            str = str.trim();
            if (!str.startsWith("LineMethod(")) {
                return null;
            }
            str = str.substring(11);
            int coords[] = new int[4];
            boolean foundparen = false;
            for (int i = 0; i < coords.length; i++) {
                int index = str.indexOf(",");
                if (index < 0) {
                    if (i < coords.length-1) {
                        return null;
                    }
                    index = str.indexOf(")");
                    if (index < 0) {
                        return null;
                    }
                    foundparen = true;
                }
                String num = str.substring(0, index).trim();
                try {
                    coords[i] = Integer.parseInt(num);
                } catch (NumberFormatException nfe) {
                    return null;
                }
                str = str.substring(index+1);
            }
            if (!foundparen || str.length() > 0) {
                return null;
            }
            LineMethod lm = new LineMethod();
            lm.line = coords;
            return lm;
        }

        private int line[] = new int[4];

        public void randomize() {
            line[0] = randIntCoord();
            line[1] = randIntCoord();
            line[2] = randIntCoord();
            line[3] = randIntCoord();
        }

        public void fill(Graphics2D g2d) {
        }

        public void draw(Graphics2D g2d) {
            g2d.drawLine(line[0], line[1], line[2], line[3]);
        }

        public String toString() {
            return ("LineMethod("+
                    line[0]+", "+
                    line[1]+", "+
                    line[2]+", "+
                    line[3]
                    +")");
        }
    }

    public static class ErrorWindow extends Frame {
        ImageCanvas unclipped;
        ImageCanvas reference;
        ImageCanvas actual;
        ImageCanvas diff;

        public ErrorWindow() {
            super("Error Comparison Window");

            unclipped = new ImageCanvas();
            reference = new ImageCanvas();
            actual = new ImageCanvas();
            diff = new ImageCanvas();

            setLayout(new SmartGridLayout(0, 2, 5, 5));
            addImagePanel(unclipped, "Unclipped rendering");
            addImagePanel(reference, "Clipped reference");
            addImagePanel(actual, "Actual clipped");
            addImagePanel(diff, "Difference");

            addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    setVisible(false);
                }
            });
        }

        public void addImagePanel(ImageCanvas ic, String label) {
            add(ic);
            add(new Label(label));
        }

        public void setImages(BufferedImage imgref, BufferedImage imgtst) {
            unclipped.setImage(imgref);
            reference.setReference(imgref);
            actual.setImage(imgtst);
            diff.setDiff(reference.getImage(), imgtst);
            invalidate();
            pack();
            repaint();
        }

        public void setVisible(boolean vis) {
            super.setVisible(vis);
            synchronized (this) {
                notifyAll();
            }
        }

        public synchronized void waitForHide() {
            while (isShowing()) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    System.exit(2);
                }
            }
        }
    }

    public static class SmartGridLayout implements LayoutManager {
        int rows;
        int cols;
        int hgap;
        int vgap;

        public SmartGridLayout(int r, int c, int h, int v) {
            this.rows = r;
            this.cols = c;
            this.hgap = h;
            this.vgap = v;
        }

        public void addLayoutComponent(String name, Component comp) {
        }

        public void removeLayoutComponent(Component comp) {
        }

        public int[][] getGridSizes(Container parent, boolean min) {
            int ncomponents = parent.getComponentCount();
            int nrows = rows;
            int ncols = cols;

            if (nrows > 0) {
                ncols = (ncomponents + nrows - 1) / nrows;
            } else {
                nrows = (ncomponents + ncols - 1) / ncols;
            }
            int widths[] = new int[ncols+1];
            int heights[] = new int[nrows+1];
            int x = 0;
            int y = 0;
            for (int i = 0 ; i < ncomponents ; i++) {
                Component comp = parent.getComponent(i);
                Dimension d = (min
                               ? comp.getMinimumSize()
                               : comp.getPreferredSize());
                if (widths[x] < d.width) {
                    widths[x] = d.width;
                }
                if (heights[y] < d.height) {
                    heights[y] = d.height;
                }
                x++;
                if (x >= ncols) {
                    x = 0;
                    y++;
                }
            }
            for (int i = 0; i < ncols; i++) {
                widths[ncols] += widths[i];
            }
            for (int i = 0; i < nrows; i++) {
                heights[nrows] += heights[i];
            }
            return new int[][] { widths, heights };
        }

        public Dimension getSize(Container parent, boolean min) {
            int sizes[][] = getGridSizes(parent, min);
            int widths[] = sizes[0];
            int heights[] = sizes[1];
            int nrows = heights.length-1;
            int ncols = widths.length-1;
            int w = widths[ncols];
            int h = heights[nrows];
            Insets insets = parent.getInsets();
            return new Dimension(insets.left+insets.right + w+(ncols+1)*hgap,
                                 insets.top+insets.bottom + h+(nrows+1)*vgap);
        }

        public Dimension preferredLayoutSize(Container parent) {
            return getSize(parent, false);
        }

        public Dimension minimumLayoutSize(Container parent) {
            return getSize(parent, true);
        }

        public void layoutContainer(Container parent) {
            int pref[][] = getGridSizes(parent, false);
            int min[][] = getGridSizes(parent, true);
            int minwidths[] = min[0];
            int minheights[] = min[1];
            int prefwidths[] = pref[0];
            int prefheights[] = pref[1];
            int nrows = minheights.length - 1;
            int ncols = minwidths.length - 1;
            Insets insets = parent.getInsets();
            int w = parent.getWidth() - insets.left - insets.right;
            int h = parent.getHeight() - insets.top - insets.bottom;
            w = w - (ncols+1)*hgap;
            h = h - (nrows+1)*vgap;
            int widths[] = calculateSizes(w, ncols, minwidths, prefwidths);
            int heights[] = calculateSizes(h, nrows, minheights, prefheights);
            int ncomponents = parent.getComponentCount();
            int x = insets.left + hgap;
            int y = insets.top + vgap;
            int r = 0;
            int c = 0;
            for (int i = 0; i < ncomponents; i++) {
                parent.getComponent(i).setBounds(x, y, widths[c], heights[r]);
                x += widths[c++] + hgap;
                if (c >= ncols) {
                    c = 0;
                    x = insets.left + hgap;
                    y += heights[r++] + vgap;
                    if (r >= nrows) {
                        // just in case
                        break;
                    }
                }
            }
        }

        public static int[] calculateSizes(int total, int num,
                                           int minsizes[], int prefsizes[])
        {
            if (total <= minsizes[num]) {
                return minsizes;
            }
            if (total >= prefsizes[num]) {
                return prefsizes;
            }
            int sizes[] = new int[total];
            int prevhappy = 0;
            int nhappy = 0;
            int happysize = 0;
            do {
                int addsize = (total - happysize) / (num - nhappy);
                happysize = 0;
                for (int i = 0; i < num; i++) {
                    if (sizes[i] >= prefsizes[i] ||
                        minsizes[i] + addsize > prefsizes[i])
                    {
                        happysize += (sizes[i] = prefsizes[i]);
                        nhappy++;
                    } else {
                        sizes[i] = minsizes[i] + addsize;
                    }
                }
            } while (nhappy < num && nhappy > prevhappy);
            return sizes;
        }
    }

    public static class ImageCanvas extends Canvas {
        BufferedImage image;

        public void setImage(BufferedImage img) {
            this.image = img;
        }

        public BufferedImage getImage() {
            return image;
        }

        public void checkImage(int w, int h) {
            if (image == null ||
                image.getWidth() < w ||
                image.getHeight() < h)
            {
                image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            }
        }

        public void setReference(BufferedImage img) {
            checkImage(img.getWidth(), img.getHeight());
            Graphics g = image.createGraphics();
            g.drawImage(img, 0, 0, null);
            g.setColor(Color.white);
            g.fillRect(0, 0, 30, 10);
            g.fillRect(30, 0, 10, 30);
            g.fillRect(10, 30, 30, 10);
            g.fillRect(0, 10, 10, 30);
            g.dispose();
        }

        public void setDiff(BufferedImage imgref, BufferedImage imgtst) {
            int w = Math.max(imgref.getWidth(), imgtst.getWidth());
            int h = Math.max(imgref.getHeight(), imgtst.getHeight());
            checkImage(w, h);
            Graphics g = image.createGraphics();
            g.drawImage(imgref, 0, 0, null);
            g.setXORMode(Color.white);
            g.drawImage(imgtst, 0, 0, null);
            g.setPaintMode();
            g.setColor(new Color(1f, 1f, 0f, 0.25f));
            g.fillRect(10, 10, 20, 20);
            g.setColor(new Color(1f, 0f, 0f, 0.25f));
            g.fillRect(0, 0, 30, 10);
            g.fillRect(30, 0, 10, 30);
            g.fillRect(10, 30, 30, 10);
            g.fillRect(0, 10, 10, 30);
            g.dispose();
        }

        public Dimension getPreferredSize() {
            if (image == null) {
                return new Dimension();
            } else {
                return new Dimension(image.getWidth(), image.getHeight());
            }
        }

        public void paint(Graphics g) {
            g.drawImage(image, 0, 0, null);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java RenderClipTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.