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

nodebox.graphics.AbstractGraphicsContext Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
package nodebox.graphics;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

public abstract class AbstractGraphicsContext implements GraphicsContext {

    // TODO: Support output mode
    protected Color.Mode colorMode;
    protected double colorRange;
    protected Color fillColor;
    protected Color strokeColor;
    protected double strokeWidth;
    protected Path path;
    protected boolean autoClosePath;
    protected boolean pathClosed;
    protected Transform.Mode transformMode;
    protected Transform transform = new Transform();
    protected ArrayList transformStack;
    protected String fontName;
    protected double fontSize;
    protected double lineHeight;
    protected Text.Align align;
    protected GraphicsContext.RectMode rectMode = GraphicsContext.RectMode.CORNER;
    protected GraphicsContext.EllipseMode ellipseMode = GraphicsContext.EllipseMode.CORNER;

    public void resetContext() {
        colorMode = Color.Mode.RGB;
        colorRange = 1;
        fillColor = new Color();
        strokeColor = null;
        strokeWidth = 1;
        path = null;
        autoClosePath = true;
        transformMode = Transform.Mode.CENTER;
        transform = new Transform();
        transformStack = new ArrayList();
        fontName = "Helvetica";
        fontSize = 24;
        lineHeight = 1.2;
        align = Text.Align.LEFT;
    }

    //// Primitives ////

    // TODO: Support rect modes.


    public RectMode rectmode() {
        return rectMode;
    }

    public RectMode rectmode(RectMode m) {
        return rectMode = m;
    }

    public RectMode rectmode(String m) {
        try {
            RectMode newMode = RectMode.valueOf(m.toUpperCase(Locale.US));
            return rectMode = newMode;
        } catch (IllegalArgumentException e) {
            throw new NodeBoxError("rectmode: available types for rectmode() are CORNER, CENTER, CORNERS and RADIUS\\n\"");
        }
    }

    public RectMode rectmode(int m) {
        try {
            RectMode newMode = RectMode.values()[m];
            return rectMode = newMode;
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new NodeBoxError("rectmode: available types for rectmode() are CORNER, CENTER, CORNERS and RADIUS\\n\"");
        }
    }

    private Path createPath() {
        Path p = new Path();
        p.setTransformDelegate(new ContextTransformDelegate(this));
        return p;
    }

    public Path Path() {
        return createPath();
    }

    public Path BezierPath() {
        return createPath();
    }

    public Path rect(Rect r) {
        return rect(r.getX(), r.getY(), r.getWidth(), r.getHeight(), true);
    }

    public Path rect(Rect r, boolean draw) {
        return rect(r.getX(), r.getY(), r.getWidth(), r.getHeight(), draw);
    }

    public Path rect(double x, double y, double width, double height) {
        return rect(x, y, width, height, true);
    }

    public Path rect(double x, double y, double width, double height, boolean draw) {
        Path p = createPath();
        switch (rectMode) {
            case CENTER:
                p.rect(x, y, width, height);
                break;
            case CORNER:
                p.cornerRect(x, y, width, height);
                break;
        }
        inheritFromContext(p);
        if (draw)
            addPath(p);
        return p;
    }

    public Path rect(Rect r, double roundness) {
        return rect(r.getX(), r.getY(), r.getWidth(), r.getHeight(), roundness, roundness, true);
    }

    public Path rect(Rect r, double roundness, boolean draw) {
        return rect(r.getX(), r.getY(), r.getWidth(), r.getHeight(), roundness, roundness, draw);
    }

    public Path rect(double x, double y, double width, double height, double roundness) {
        return rect(x, y, width, height, roundness, roundness, true);
    }

    public Path rect(double x, double y, double width, double height, double roundness, boolean draw) {
        return rect(x, y, width, height, roundness, roundness, draw);
    }

    public Path rect(double x, double y, double width, double height, double rx, double ry) {
        return rect(x, y, width, height, rx, ry, true);
    }

    public Path rect(double x, double y, double width, double height, double rx, double ry, boolean draw) {
        Path p = createPath();
        switch (rectMode) {
            case CENTER:
                p.rect(x, y, width, height, rx, ry);
                break;
            case CORNER:
                p.cornerRect(x, y, width, height, rx, ry);
                break;
        }
        inheritFromContext(p);
        if (draw)
            addPath(p);
        return p;
    }

    public EllipseMode ellipsemode() {
        return ellipseMode;
    }

    public EllipseMode ellipsemode(EllipseMode m) {
        return ellipseMode = m;
    }

    public EllipseMode ellipsemode(String m) {
        try {
            EllipseMode newMode = EllipseMode.valueOf(m.toUpperCase(Locale.US));
            return ellipseMode = newMode;
        } catch (IllegalArgumentException e) {
            throw new NodeBoxError("ellipsemode: available types for ellipsemode() are CORNER, CENTER, CORNERS and RADIUS\\n\"");
        }
    }

    public EllipseMode ellipsemode(int m) {
        try {
            EllipseMode newMode = EllipseMode.values()[m];
            return ellipseMode = newMode;
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new NodeBoxError("ellipsemode: available types for ellipsemode() are CORNER, CENTER, CORNERS and RADIUS\\n\"");
        }
    }

    public Path oval(double x, double y, double width, double height) {
        // TODO: Deprecation warning
        return ellipse(x, y, width, height, true);
    }

    public Path oval(double x, double y, double width, double height, boolean draw) {
        // TODO: Deprecation warning
        return ellipse(x, y, width, height, draw);
    }

    public Path ellipse(double x, double y, double width, double height) {
        return ellipse(x, y, width, height, true);
    }

    public Path ellipse(double x, double y, double width, double height, boolean draw) {
        Path p = createPath();
        switch (ellipseMode) {
            case CENTER:
                p.ellipse(x, y, width, height);
                break;
            case CORNER:
                p.cornerEllipse(x, y, width, height);
                break;
        }
        inheritFromContext(p);
        if (draw)
            addPath(p);
        return p;
    }

    public Path line(double x1, double y1, double x2, double y2) {
        return line(x1, y1, x2, y2, true);
    }

    public Path line(double x1, double y1, double x2, double y2, boolean draw) {
        Path p = createPath();
        p.line(x1, y1, x2, y2);
        inheritFromContext(p);
        if (draw)
            addPath(p);
        return p;
    }

    public Path star(double cx, double cy) {
        return star(cx, cy, 20, 100, 50, true);
    }

    public Path star(double cx, double cy, int points) {
        return star(cx, cy, points, 100, 50, true);
    }

    public Path star(double cx, double cy, int points, double outer) {
        return star(cx, cy, points, outer, 50, true);
    }

    public Path star(double cx, double cy, int points, double outer, double inner) {
        return star(cx, cy, points, outer, inner, true);
    }

    public Path star(double cx, double cy, int points, double outer, double inner, boolean draw) {
        double PI = (double) Math.PI;
        Path p = createPath();
        p.moveto(cx, cy + outer);
        for (int i = 1; i < points * 2; i++) {
            double angle = i * PI / points;
            double x = (double) Math.sin(angle);
            double y = (double) Math.cos(angle);
            double radius = i % 2 == 0 ? outer : inner;
            x += cx + radius * x;
            y += cy + radius * y;
            p.lineto(x, y);
        }
        p.close();
        inheritFromContext(p);
        if (draw)
            addPath(p);
        return p;
    }

    public Path arrow(double x, double y) {
        return arrow(x, y, 100, ArrowType.NORMAL, true);
    }

    public Path arrow(double x, double y, ArrowType type) {
        return arrow(x, y, 100, type, true);
    }

    public Path arrow(double x, double y, String type) {
        return arrow(x, y, 100, type, true);
    }

    public Path arrow(double x, double y, int type) {
        return arrow(x, y, 100, type, true);
    }

    public Path arrow(double x, double y, double width) {
        return arrow(x, y, width, NORMAL, true);
    }

    public Path arrow(double x, double y, double width, boolean draw) {
        return arrow(x, y, width, NORMAL, draw);
    }

    public Path arrow(double x, double y, double width, ArrowType type) {
        return arrow(x, y, width, type, true);
    }

    public Path arrow(double x, double y, double width, String type) {
        return arrow(x, y, width, type, true);
    }

    public Path arrow(double x, double y, double width, int type) {
        return arrow(x, y, width, type, true);
    }

    public Path arrow(double x, double y, double width, String type, boolean draw) {
        try {
            ArrowType arrowType = ArrowType.valueOf(type.toUpperCase(Locale.US));
            return arrow(x, y, width, arrowType, draw);
        } catch (IllegalArgumentException e) {
            throw new NodeBoxError("arrow: available types for arrow() are NORMAL and FORTYFIVE\\n\"");
        }
    }

    public Path arrow(double x, double y, double width, int type, boolean draw) {
        try {
            ArrowType arrowType = ArrowType.values()[type];
            return arrow(x, y, width, arrowType, draw);
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new NodeBoxError("arrow: available types for arrow() are NORMAL and FORTYFIVE\\n\"");
        }
    }

    public Path arrow(double x, double y, double width, ArrowType type, boolean draw) {
        if (type == ArrowType.NORMAL)
            return arrowNormal(x, y, width, draw);
        else
            return arrowFortyFive(x, y, width, draw);
    }

    private Path arrowNormal(double x, double y, double width, boolean draw) {
        double head = width * .4;
        double tail = width * .2;

        Path p = createPath();
        p.moveto(x, y);
        p.lineto(x - head, y + head);
        p.lineto(x - head, y + tail);
        p.lineto(x - width, y + tail);
        p.lineto(x - width, y - tail);
        p.lineto(x - head, y - tail);
        p.lineto(x - head, y - head);
        p.lineto(x, y);
        p.close();
        inheritFromContext(p);
        if (draw)
            addPath(p);
        return p;
    }

    private Path arrowFortyFive(double x, double y, double width, boolean draw) {
        double head = .3;
        double tail = 1 + head;

        Path p = createPath();
        p.moveto(x, y);
        p.lineto(x, y + width * (1 - head));
        p.lineto(x - width * head, y + width);
        p.lineto(x - width * head, y + width * tail * .4);
        p.lineto(x - width * tail * .6, y + width);
        p.lineto(x - width, y + width * tail * .6);
        p.lineto(x - width * tail * .4, y + width * head);
        p.lineto(x - width, y + width * head);
        p.lineto(x - width * (1 - head), y);
        p.lineto(x, y);
        p.close();
        inheritFromContext(p);
        if (draw)
            addPath(p);
        return p;
    }

    //// Path commands ////

    public void beginpath() {
        path = createPath();
        pathClosed = false;
    }

    public void beginpath(double x, double y) {
        beginpath();
        moveto(x, y);
    }

    public void moveto(double x, double y) {
        if (path == null)
            throw new NodeBoxError("No current path. Use beginpath() first.");
        path.moveto(x, y);
    }

    public void lineto(double x, double y) {
        if (path == null)
            throw new NodeBoxError("No current path. Use beginpath() first.");
        path.lineto(x, y);
    }

    public void curveto(double x1, double y1, double x2, double y2, double x3, double y3) {
        if (path == null)
            throw new NodeBoxError("No current path. Use beginPath() first.");
        path.curveto(x1, y1, x2, y2, x3, y3);
    }

    public void closepath() {
        if (path == null)
            throw new NodeBoxError("No current path. Use beginpath() first.");
        if (!pathClosed) {
            path.close();
            pathClosed = true;
        }
    }

    public Path endpath() {
        return endpath(true);
    }

    public Path endpath(boolean draw) {
        if (path == null)
            throw new NodeBoxError("No current path. Use beginpath() first.");
        if (autoClosePath)
            closepath();
        Path p = path;
        inheritFromContext(p);
        if (draw)
            addPath(p);
        // Initialize a new path
        path = null;
        pathClosed = false;
        return p;
    }

    public void drawpath(Path path) {
        inheritFromContext(path);
        addPath(path);
    }

    public void drawpath(Iterable points) {
        Path path = createPath();
        for (Point pt : points) {
            path.addPoint(pt);
        }
        inheritFromContext(path);
        addPath(path);
    }

    public boolean autoclosepath() {
        return autoClosePath;
    }

    public boolean autoclosepath(boolean c) {
        return autoClosePath = c;
    }

    public Path findpath(List points) {
        return findpath(points, 1);
    }

    public Path findpath(List points, double curvature) {
        Path path = Path.findPath(points, curvature);
        inheritFromContext(path);
        addPath(path);
        return path;
    }

    //// Clipping ////

    // TODO: implement clipping

    public void beginclip(Path p) {
        throw new RuntimeException("beginclip is not implemented yet.");
    }

    public void endclip() {
        throw new RuntimeException("endclip is not implemented yet.");
    }


    //// Transformation commands ////


    public Transform.Mode transform() {
        return transformMode;
    }

    public Transform.Mode transform(Transform.Mode mode) {
        return transformMode = mode;
    }

    public Transform.Mode transform(String mode) {
        try {
            Transform.Mode newMode = Transform.Mode.valueOf(mode.toUpperCase(Locale.US));
            return transformMode = newMode;
        } catch (IllegalArgumentException e) {
            throw new NodeBoxError("transform: available types for transform() are CORNER and CENTER\\n\"");
        }
    }

    public Transform.Mode transform(int mode) {
        try {
            Transform.Mode newMode = Transform.Mode.values()[mode];
            return transformMode = newMode;
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new NodeBoxError("transform: available types for transform() are CORNER and CENTER\\n\"");
        }
    }

    public void push() {
        transformStack.add(0, transform.clone());
    }

    public void pop() {
        if (transformStack.isEmpty())
            throw new NodeBoxError("Pop: too many pops!");
        transform = transformStack.get(0);
        transformStack.remove(0);
    }

    public void reset() {
        transformStack.clear();
        transform = new Transform();
    }

    public void translate(double tx, double ty) {
        transform.translate(tx, ty);
    }

    public void rotate(double r) {
        transform.rotate(r);
    }

    public void scale(double scale) {
        transform.scale(scale);
    }

    public void scale(double sx, double sy) {
        transform.scale(sx, sy);
    }

    public void skew(double skew) {
        transform.skew(skew);
    }

    public void skew(double kx, double ky) {
        transform.skew(kx, ky);
    }

    //// Color commands ////

    public String outputmode() {
        throw new RuntimeException("outputmode is not implemented yet.");
    }

    public String outputmode(String mode) {
        throw new RuntimeException("outputmode is not implemented yet.");
    }

    public Color.Mode colormode() {
        return colorMode;
    }

    public Color.Mode colormode(Color.Mode mode) {
        return colorMode = mode;
    }

    public Color.Mode colormode(Color.Mode mode, double range) {
        colorRange = range;
        return colorMode = mode;
    }

    public Color.Mode colormode(String mode) {
        return colormode(mode, colorRange);
    }

    public Color.Mode colormode(String mode, double range) {
        try {
            Color.Mode newMode = Color.Mode.valueOf(mode.toUpperCase(Locale.US));
            return colormode(newMode, range);
        } catch (IllegalArgumentException e) {
            throw new NodeBoxError("colormode: available types for colormode() are RGB, HSB and CMYK\\n\"");
        }
    }

    public Color.Mode colormode(int mode) {
        return colormode(mode, colorRange);
    }

    public Color.Mode colormode(int mode, double range) {
        try {
            Color.Mode newMode = Color.Mode.values()[mode];
            return colormode(newMode, range);
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new NodeBoxError("colormode: available types for colormode() are RGB, HSB and CMYK\\n\"");
        }
    }

    public double colorrange() {
        return colorRange;
    }

    public double colorrange(double range) {
        return colorRange = range;
    }

    /**
     * Create an empty (black) color object.
     *
     * @return the new color.
     */
    public Color color() {
        return new Color();
    }

    /**
     * Create a new color with the given grayscale value.
     *
     * @param x the gray component.
     * @return the new color.
     */
    public Color color(double x) {
        double nx = normalize(x);
        return new Color(nx, nx, nx);
    }

    /**
     * Create a new color with the given grayscale and alpha value.
     *
     * @param x the grayscale value.
     * @param y the alpha value.
     * @return the new color.
     */
    public Color color(double x, double y) {
        double nx = normalize(x);
        return new Color(nx, nx, nx, normalize(y));
    }

    /**
     * Create a new color with the the given R/G/B or H/S/B value.
     *
     * @param x the red or hue component.
     * @param y the green or saturation component.
     * @param z the blue or brightness component.
     * @return the new color.
     */
    public Color color(double x, double y, double z) {
        return new Color(normalize(x), normalize(y), normalize(z), colormode());
    }

    /**
     * Create a new color with the the given R/G/B/A or H/S/B/A value.
     *
     * @param x the red or hue component.
     * @param y the green or saturation component.
     * @param z the blue or brightness component.
     * @param a the alpha component.
     * @return the new color.
     */
    public Color color(double x, double y, double z, double a) {
        return new Color(normalize(x), normalize(y), normalize(z), normalize(a), colormode());
    }

    /**
     * Create a new color with the the given color.
     * 

* The color object is cloned; you can change the original afterwards. * If the color object is null, the new color is turned off (same as nocolor). * * @param c the color object. * @return the new color. */ public Color color(Color c) { return c == null ? new Color(0, 0, 0, 0) : c.clone(); } /** * Get the current fill color. * * @return the current fill color. */ public Color fill() { return fillColor; } /** * Set the current fill color to given grayscale value. * * @param x the gray component. * @return the current fill color. */ public Color fill(double x) { double nx = normalize(x); return fillColor = new Color(nx, nx, nx); } /** * Set the current fill color to given grayscale and alpha value. * * @param x the grayscale value. * @param y the alpha value. * @return the current fill color. */ public Color fill(double x, double y) { double nx = normalize(x); return fillColor = new Color(nx, nx, nx, normalize(y)); } /** * Set the current fill color to the given R/G/B or H/S/B value. * * @param x the red or hue component. * @param y the green or saturation component. * @param z the blue or brightness component. * @return the current fill color. */ public Color fill(double x, double y, double z) { return fillColor = new Color(normalize(x), normalize(y), normalize(z), colormode()); } /** * Set the current fill color to the given R/G/B/A or H/S/B/A value. * * @param x the red or hue component. * @param y the green or saturation component. * @param z the blue or brightness component. * @param a the alpha component. * @return the current fill color. */ public Color fill(double x, double y, double z, double a) { return fillColor = new Color(normalize(x), normalize(y), normalize(z), normalize(a), colormode()); } /** * Set the current fill color to the given color. *

* The color object is cloned; you can change the original afterwards. * If the color object is null, the current fill color is turned off (same as nofill). * * @param c the color object. * @return the current fill color. */ public Color fill(Color c) { return fillColor = c == null ? null : c.clone(); } public void nofill() { fillColor = null; } /** * Get the current stroke color. * * @return the current stroke color. */ public Color stroke() { return strokeColor; } /** * Set the current stroke color to given grayscale value. * * @param x the gray component. * @return the current stroke color. */ public Color stroke(double x) { double nx = normalize(x); return strokeColor = new Color(nx, nx, nx); } /** * Set the current stroke color to given grayscale and alpha value. * * @param x the grayscale value. * @param y the alpha value. * @return the current stroke color. */ public Color stroke(double x, double y) { double nx = normalize(x); return strokeColor = new Color(nx, nx, nx, normalize(y)); } /** * Set the current stroke color to the given R/G/B or H/S/B value. * * @param x the red or hue component. * @param y the green or saturation component. * @param z the blue or brightness component. * @return the current stroke color. */ public Color stroke(double x, double y, double z) { return strokeColor = new Color(normalize(x), normalize(y), normalize(z), colormode()); } /** * Set the current stroke color to the given R/G/B/A or H/S/B/A value. * * @param x the red or hue component. * @param y the green or saturation component. * @param z the blue or brightness component. * @param a the alpha component. * @return the current stroke color. */ public Color stroke(double x, double y, double z, double a) { return strokeColor = new Color(normalize(x), normalize(y), normalize(z), normalize(a), colormode()); } /** * Set the current stroke color to the given color. *

* The color object is cloned; you can change the original afterwards. * If the color object is null, the current stroke color is turned off (same as nostroke). * * @param c the color object. * @return the current stroke color. */ public Color stroke(Color c) { return strokeColor = c == null ? null : c.clone(); } public void nostroke() { strokeColor = null; } public double strokewidth() { return strokeWidth; } public double strokewidth(double w) { return strokeWidth = w; } //// Image commands //// public Image image(String path, double x, double y) { throw new RuntimeException("'image' is not applicable to this type of GraphicsContext."); } public Image image(String path, double x, double y, double width) { throw new RuntimeException("'image' is not applicable to this type of GraphicsContext."); } public Image image(String path, double x, double y, double width, double height) { throw new RuntimeException("'image' is not applicable to this type of GraphicsContext."); } public Image image(String path, double x, double y, double width, double height, double alpha) { throw new RuntimeException("'image' is not applicable to this type of GraphicsContext."); } public Image image(String path, double x, double y, double width, double height, boolean draw) { throw new RuntimeException("'image' is not applicable to this type of GraphicsContext."); } public Image image(String path, double x, double y, double width, double height, double alpha, boolean draw) { throw new RuntimeException("'image' is not applicable to this type of GraphicsContext."); } public Image image(Image img, double x, double y, double width, double height, double alpha, boolean draw) { throw new RuntimeException("'image' is not applicable to this type of GraphicsContext."); } public Image image(BufferedImage img, double x, double y, double width, double height, double alpha, boolean draw) { throw new RuntimeException("'image' is not applicable to this type of GraphicsContext."); } public Size imagesize(String path) { throw new RuntimeException("'imagesize' is not applicable to this type of GraphicsContext."); } public Size imagesize(Image img) { throw new RuntimeException("'imagesize' is not applicable to this type of GraphicsContext."); } public Size imagesize(BufferedImage img) { throw new RuntimeException("'imagesize' is not applicable to this type of GraphicsContext."); } //// Font commands //// public String font() { return fontName; } public String font(String fontName) { if (!Text.fontExists(fontName)) throw new NodeBoxError("Font '" + fontName + "' does not exist."); return this.fontName = fontName; } public String font(String fontName, double fontSize) { font(fontName); fontsize(fontSize); return fontName; } public double fontsize() { return fontSize; } public double fontsize(double s) { return fontSize = s; } public double lineheight() { return lineHeight; } public double lineheight(double lineHeight) { return this.lineHeight = lineHeight; } public Text.Align align() { return align; } public Text.Align align(Text.Align align) { return this.align = align; } public Text.Align align(String align) { try { Text.Align newAlign = Text.Align.valueOf(align.toUpperCase(Locale.US)); return this.align = newAlign; } catch (IllegalArgumentException e) { throw new NodeBoxError("align: available types for align() are LEFT, RIGHT, CENTER and JUSTIFY\\n\""); } } public Text.Align align(int align) { try { Text.Align newAlign = Text.Align.values()[align]; return this.align = newAlign; } catch (ArrayIndexOutOfBoundsException e) { throw new NodeBoxError("align: available types for align() are LEFT, RIGHT, CENTER and JUSTIFY\\n\""); } } public Text text(String text, double x, double y) { return text(text, x, y, 0, 0, true); } public Text text(String text, double x, double y, double width) { return text(text, x, y, width, 0, true); } public Text text(String text, double x, double y, double width, double height) { return text(text, x, y, width, height, true); } public Text text(String text, double x, double y, double width, double height, boolean draw) { Text t = new Text(text, x, y, width, height); t.setTransformDelegate(new ContextTransformDelegate(this)); inheritFromContext(t); if (draw) addText(t); return t; } public Path textpath(String text, double x, double y) { return textpath(text, x, y, 0, 0); } public Path textpath(String text, double x, double y, double width) { return textpath(text, x, y, width, 0); } public Path textpath(String text, double x, double y, double width, double height) { Text t = new Text(text, x, y, width, height); inheritFontAttributesFromContext(t); Path path = t.getPath(); path.setTransformDelegate(new ContextTransformDelegate(this)); inheritFromContext(path); return path; } public Rect textmetrics(String text) { return textmetrics(text, 0, 0); } public Rect textmetrics(String text, double width) { return textmetrics(text, width, 0); } public Rect textmetrics(String text, double width, double height) { Text t = new Text(text, 0, 0, width, height); inheritFromContext(t); return t.getMetrics(); } public double textwidth(String text) { return textmetrics(text, 0, 0).getWidth(); } public double textwidth(String text, double width) { return textmetrics(text, width).getWidth(); } public double textheight(String text) { return textmetrics(text, 0, 0).getHeight(); } public double textheight(String text, double width) { return textmetrics(text, width).getHeight(); } //// Utility methods //// public void var(String name, VarType type) { var(name, type, null, 0, 1000); } public void var(String name, String type) { var(name, type, null, 0, 1000); } public void var(String name, int type) { var(name, type, 0, 0, 1000); } public void var(String name, VarType type, Object value) { var(name, type, value, 0, 1000); } public void var(String name, String type, Object value) { var(name, type, value, 0, 1000); } public void var(String name, int type, Object value) { var(name, type, value, 0, 1000); } public void var(String name, String type, Object value, double min, double max) { try { var(name, VarType.valueOf(type.toUpperCase(Locale.US)), value, min, max); } catch (IllegalArgumentException e) { throw new NodeBoxError("var: available types for var() are NUMBER, TEXT, BOOLEAN and FONT \\n\""); } } public void var(String name, int type, Object value, double min, double max) { try { var(name, VarType.values()[type], value, min, max); } catch (ArrayIndexOutOfBoundsException e) { throw new NodeBoxError("var: available types for var() are NUMBER, TEXT, BOOLEAN and FONT \\n\""); } } public void var(String name, VarType type, Object value, double min, double max) { // Node node = ProcessingContext.getCurrentContext().getNode(); // if (node == null) return; // Parameter p = node.getInput(name); // if (p != null) { // if (p.getType() != type.type) { // p.setType(type.type); // } // if (p.getWidget() != type.widget) { // p.setWidget(type.widget); // } // if (p.getMinimumValue() != null && !p.getMinimumValue().equals(min)) { // p.setMinimumValue(min); // } // if (p.getMaximumValue() != null && !p.getMaximumValue().equals(max)) { // p.setMaximumValue(max); // } // } else { // p = node.addPort(name, type.type); // p.setWidget(type.widget); // if (value != null) { // p.setValue(value); // } // if (min != null || max != null) { // p.setBoundingMethod(Parameter.BoundingMethod.HARD); // p.setMinimumValue(min); // p.setMaximumValue(max); // } // node.updateDependencies(ProcessingContext.getCurrentContext()); // } } public Object findVar(String name) { // Node node = ProcessingContext.getCurrentContext().getNode(); // if (node == null) return null; // return node.getInput(name); return null; } protected double normalize(double v) { // Bring the color into the 0-1 scale for the current colorrange if (colorRange == 1) return v; return v / colorRange; } public double random() { return Math.random(); } public long random(int max) { return Math.round(Math.random() * max); } public long random(int min, int max) { return Math.round(min + (Math.random() * (max - min))); } public double random(double max) { return Math.random() * max; } public double random(double min, double max) { return min + (Math.random() * (max - min)); } public Object choice(List objects) { if (objects == null || objects.isEmpty()) return null; return objects.get((int) random(objects.size() - 1)); } public Iterator grid(int columns, int rows) { return grid(columns, rows, 1, 1); } public Iterator grid(double columns, double rows) { return grid(Math.round(columns), Math.round(rows), 1, 1); } public Iterator grid(double columns, double rows, double columnSize, double rowSize) { return grid(Math.round(columns), Math.round(rows), columnSize, rowSize); } public Iterator grid(final int columns, final int rows, final double columnSize, final double rowSize) { return new Iterator() { int x = 0; int y = 0; public boolean hasNext() { return y < rows; } public Point next() { Point pt = new Point((double) (x * columnSize), (double) (y * rowSize)); x++; if (x >= columns) { x = 0; y++; } return pt; } public void remove() { } }; } //// Context drawing ///// public void draw(Grob g) { if (g instanceof Path) { addPath((Path) g); } else if (g instanceof Geometry) { for (Path path : ((Geometry) g).getPaths()) { addPath(path); } } else if (g instanceof Contour) { addPath(((Contour) g).toPath()); } else if (g instanceof Text) { addText((Text) g); } else { throw new IllegalArgumentException("Don't know how to add a " + g + " to the current context."); } } protected abstract void addPath(Path p); protected abstract void addText(Text t); protected void inheritFromContext(Path p) { p.setFillColor(fillColor == null ? null : fillColor.clone()); p.setStrokeColor(strokeColor == null ? null : strokeColor.clone()); p.setStrokeWidth(strokeWidth); TransformDelegate d = p.getTransformDelegate(); d.transform(p, transform, true); } protected void inheritFromContext(Text t) { t.setFillColor(fillColor == null ? null : fillColor.clone()); inheritFontAttributesFromContext(t); // todo: check if this is sufficient. TransformDelegate d = t.getTransformDelegate(); d.transform(t, transform, true); /* Rect r = t.getBounds(); double dx = r.getX() + r.getWidth() / 2; double dy = r.getY() + r.getHeight() / 2; if (transformMode == Transform.Mode.CENTER) { Transform trans = new Transform(); trans.translate(dx, dy); trans.append(transform); trans.translate(-dx, -dy); t.setTransform(trans); } else { t.setTransform(transform); } */ } private void inheritFontAttributesFromContext(Text t) { t.setFontName(fontName); t.setFontSize(fontSize); t.setLineHeight(lineHeight); t.setAlign(align); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy