Example usage for java.awt Graphics drawRect

List of usage examples for java.awt Graphics drawRect

Introduction

In this page you can find the example usage for java.awt Graphics drawRect.

Prototype

public void drawRect(int x, int y, int width, int height) 

Source Link

Document

Draws the outline of the specified rectangle.

Usage

From source file:stainingestimation.StainingEstimation.java

/**
 * Performs nucleus finding on the given color chanel image imp (heatmap) with the given parameters. Nuclei are drawn on the image.
 * @param imp The gray scaled color channel image after color deconvolution. It is altered by the method.
 * @param blur The blur parameter before nucleus detection.
 * @param tolerance The tolerance parameter of the local maximum method.
 * @param tmap The grayscaled image (same size as imp). Each pixel give a minimum value of a local maximum at this point.
 *//*from w w  w  .  j  a  v a 2 s.  c om*/
void calculateNucleiPreview(ImagePlus imp, double blur, int tolerance, ImagePlus tmap) {
    List<TMApoint> tps = StainingEstimation.find_nucleus_lm(null, imp.duplicate(), 0, 0, blur, tolerance, tmap,
            TMALabel.STAINING_0, true);
    new ImageConverter(imp).convertToRGB();
    Graphics g = imp.getImage().getGraphics();
    g.setColor(Color.RED);
    for (TMApoint tp : tps) {
        g.drawRect(tp.x - 1, tp.y - 1, 3, 3);
    }
}

From source file:org.kineticsystem.commons.layout.TetrisLayout.java

/**
 * <p>This method draws the layout on a graphics context. Used to test the
 * layout during the design process. Override the 
 * <code>paint(Graphics g)</code> of the container to display the layout.
 * Here is an example code where <code>layout</code> is a 
 * <code>TestrisLayout</code>.</p>
 * <pre>/*from w ww  .  j av  a 2 s.  c o  m*/
 * JPanel panel = new JPanel(layout) {
 *     public void paint(Graphics g) {
 *         super.paint(g);
 *         ((TetrisLayout) getLayout()).drawLayout(g);
 *     }
 * };
 * </pre>
 * @param g The graphics context.
 */
public void drawLayout(Graphics g) {

    // Draw the spanning layout.

    g.setColor(spanningLayoutColor);

    Insets insets = container.getInsets();
    Dimension size = container.getSize();

    int actualGapFreeWidth = Math
            .max(size.width - insets.left - insets.right - cGaps[cBars.length].getIncSize(), 0);
    int actualGapFreeHeight = Math
            .max(size.height - insets.top - insets.bottom - rGaps[rBars.length].getIncSize(), 0);

    for (Cell cell : constraintsMap.values()) {

        if (cell != null) {

            /*
             * Calculate the center of the first and the last cell spanned
             * by the current component.
             */

            int cx0 = (int) Math.round((cSizes[cell.getCol()].evaluate(actualGapFreeWidth)
                    + cSizes[cell.getCol() + 1].evaluate(actualGapFreeWidth)) / 2);
            int cy0 = (int) Math.round((rSizes[cell.getRow()].evaluate(actualGapFreeHeight)
                    + rSizes[cell.getRow() + 1].evaluate(actualGapFreeHeight)) / 2);
            int cx1 = (int) Math.round((cSizes[cell.getCol() + cell.getCols()].evaluate(actualGapFreeWidth)
                    + cSizes[cell.getCol() + cell.getCols() - 1].evaluate(actualGapFreeWidth)) / 2) + 1;
            int cy1 = (int) Math.round((rSizes[cell.getRow() + cell.getRows()].evaluate(actualGapFreeHeight)
                    + rSizes[cell.getRow() + cell.getRows() - 1].evaluate(actualGapFreeHeight)) / 2) + 1;

            // Actual cell dimension.

            int w = cx1 - cx0;
            int h = cy1 - cy0;

            // Component position correction.

            int xCorrection = insets.left + cGaps[cell.getCol()].getIncSize();
            int yCorrection = insets.top + rGaps[cell.getRow()].getIncSize();

            // Component dimension correction.

            int wCorrection = cGaps[cell.getCol() + cell.getCols() - 1].getIncSize()
                    - cGaps[cell.getCol()].getIncSize();
            int hCorrection = rGaps[cell.getRow() + cell.getRows() - 1].getIncSize()
                    - rGaps[cell.getRow()].getIncSize();

            cx0 += xCorrection;
            cy0 += yCorrection;
            w += wCorrection;
            h += hCorrection;

            int radius = 6;
            g.drawRect(cx0 + 1, cy0 + 1, w - 1, h - 1);
            g.drawOval(cx0 + 1 - radius / 2, cy0 + 1 - radius / 2, radius, radius);
            g.drawOval(cx0 + w - radius / 2, cy0 + h - radius / 2, radius, radius);
        }
    }

    // Draw the internal layout.

    g.setColor(internalLayoutColor);

    int x2 = (int) Math.round(cSizes[cSizes.length - 1].evaluate(actualGapFreeWidth)
            + cGaps[cSizes.length - 1].getIncSize() + insets.left) - 1;
    int y2 = (int) Math.round(rSizes[rSizes.length - 1].evaluate(actualGapFreeHeight)
            + rGaps[rSizes.length - 1].getIncSize() + insets.top) - 1;

    for (int i = 1; i < cSizes.length - 1; i++) {
        int x = (int) Math
                .round(cSizes[i].evaluate(actualGapFreeWidth) + insets.left + cGaps[i - 1].getIncSize());
        g.drawLine(x, insets.top, x, y2);
        g.drawLine(x + cGaps[i].getSize(), insets.top, x + cGaps[i].getSize(), y2);
    }
    for (int i = 1; i < rSizes.length - 1; i++) {
        int y = (int) Math
                .round(rSizes[i].evaluate(actualGapFreeHeight) + insets.top + rGaps[i - 1].getIncSize());
        g.drawLine(insets.left, y, x2, y);
        g.drawLine(insets.left, y + rGaps[i].getSize(), x2, y + rGaps[i].getSize());
    }

    // Draw the layout internal frame.

    g.setColor(externalLayoutColor);
    g.drawRect(insets.left, insets.top, x2 - insets.left, y2 - insets.top);

    // Draw layout external frame.

    g.drawRect(0, 0, x2 + insets.right, y2 + insets.bottom);
}

From source file:org.processmining.analysis.performance.dottedchart.ui.DottedChartPanel.java

/**
 * convenience method for internal use. paints a log item handle
 * visualization.//from  w w  w.ja v a  2s .c o  m
 * 
 * @param x
 *            horizontal anchor coordinate of the handle
 * @param y
 *            vertical anchor coordinate of the handle
 * @param g
 *            the Graphics object used for painting
 */
protected void paintHighligtedItem(int x, int y, Graphics g, String shape) {
    Color color = g.getColor();
    if (shape.equals(STR_NONE)) {
        return;
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_DOT)) {
        if (!color.equals(Color.red))
            g.setColor(Color.red);
        else
            g.setColor(Color.black);
        g.fillOval(x - 3, y - 3, 6, 6);
        g.setColor(color);
        g.fillOval(x - 2, y - 2, 4, 4);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_BOX)) {
        if (!color.equals(Color.black))
            g.setColor(Color.black);
        else
            g.setColor(Color.red);
        g.fillRect(x - 6, y - 6, 12, 12);
        g.setColor(color);
        g.fill3DRect(x - 5, y - 5, 10, 10, false);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_CIRCLE)) {
        if (!color.equals(Color.black))
            g.setColor(Color.black);
        else
            g.setColor(Color.red);
        g.fillOval(x - 6, y - 6, 13, 13);
        g.setColor(color);
        g.fillOval(x - 5, y - 5, 11, 11);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_RHOMBUS)) {
        int rhombX[] = { x, x - 5, x, x + 5 };
        int rhombY[] = { y - 5, y, y + 5, y };
        g.fillPolygon(rhombX, rhombY, 4);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_TRIANGLE)) {
        int triX[] = { x, x - 5, x + 5 };
        int triY[] = { y + 5, y - 5, y - 5 };
        g.fillPolygon(triX, triY, 3);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_ROUND_BOX)) {
        if (!color.equals(Color.black))
            g.setColor(Color.black);
        else
            g.setColor(Color.red);
        g.fillRoundRect(x - 6, y - 6, 13, 13, 2, 2);
        g.setColor(color);
        g.fillRoundRect(x - 5, y - 5, 10, 10, 2, 2);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_DRAW_BOX)) {
        g.drawRect(x - 5, y - 5, 10, 10);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_DRAW_CIRCLE)) {
        if (!color.equals(Color.black))
            g.setColor(Color.black);
        else
            g.setColor(Color.red);
        g.fillOval(x - 6, y - 6, 13, 13);
        g.setColor(color);
        g.drawOval(x - 5, y - 5, 11, 11);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_DRAW_RHOMBUS)) {
        int rhombX[] = { x, x - 5, x, x + 5 };
        int rhombY[] = { y - 5, y, y + 5, y };
        g.drawPolygon(rhombX, rhombY, 4);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_DRAW_TRIANGLE)) {
        int triX[] = { x, x - 5, x + 5 };
        int triY[] = { y + 5, y - 5, y - 5 };
        g.drawPolygon(triX, triY, 3);
    } else if (shape.equals(DottedChartPanel.ITEM_HANDLE_DRAW_ROUND_BOX)) {
        g.drawRoundRect(x - 5, y - 5, 10, 10, 2, 2);
    }
}

From source file:com.actelion.research.table.view.JVisualization.java

protected void drawSelectionOutline(Graphics g) {
    g.setColor(VisualizationColor.cSelectedColor);
    if (mRectangleSelecting)
        g.drawRect((mMouseX1 < mMouseX2) ? mMouseX1 : mMouseX2, (mMouseY1 < mMouseY2) ? mMouseY1 : mMouseY2,
                Math.abs(mMouseX2 - mMouseX1), Math.abs(mMouseY2 - mMouseY1));

    if (mLassoSelecting)
        g.drawPolygon(mLassoRegion);//from  w ww . j a v a2 s  .  c o  m
}

From source file:org.processmining.analysis.performance.advanceddottedchartanalysis.ui.DottedChartPanel.java

/**
 * paints this log item panel and all contained log items as specified.
 * /*from  ww w.j a  va2  s  .  c  o m*/
 * @param g
 *            the graphics object used for painting
 */
public void paintComponent(Graphics grx) {
    Graphics gr = grx.create();

    if (this.isOpaque()) {
        gr.setColor(colorBg);
        gr.fillRect(0, 0, getWidth(), getHeight());
    }

    if ((int) gr.getClipBounds().getMinX() < coUtil.getClipL()
            || (int) gr.getClipBounds().getMaxX() > coUtil.getClipR()
            || (int) gr.getClipBounds().getMinY() < coUtil.getClipU()
            || (int) gr.getClipBounds().getMaxY() > coUtil.getClipB()) {
        modelBuffer = null;
    }

    if (modelBuffer == null) {
        this.setToolTipText(null);

        if (this.getWidth() <= SCREENLENGTH) {
            coUtil.setClipL(0);
            coUtil.setClipR(this.getWidth());
        } else {
            int x1 = (SCREENLENGTH - gr.getClipBounds().width) / 2;
            int x2 = (int) gr.getClipBounds().getMinX() - x1;
            if (x2 <= 0) {
                coUtil.setClipL(0);
                coUtil.setClipR(SCREENLENGTH);
            } else if (x2 + SCREENLENGTH >= this.getWidth()) {
                coUtil.setClipR(this.getWidth());
                coUtil.setClipL(this.getWidth() - SCREENLENGTH);
            } else {
                coUtil.setClipL(x2);
                coUtil.setClipR(x2 + SCREENLENGTH);
            }
        }
        if (this.getHeight() <= SCREENLENGTH) {
            coUtil.setClipU(0);
            coUtil.setClipB(this.getHeight());
        } else {
            int y1 = (SCREENLENGTH - gr.getClipBounds().height) / 2;
            int y2 = (int) gr.getClipBounds().getMinY() - y1;
            if (y2 <= 0) {
                coUtil.setClipU(0);
                coUtil.setClipB(SCREENLENGTH);
            } else if (y2 + SCREENLENGTH >= this.getHeight()) {
                coUtil.setClipU(this.getHeight() - SCREENLENGTH);
                coUtil.setClipB(this.getHeight());
            } else {
                coUtil.setClipU(y2);
                coUtil.setClipB(y2 + SCREENLENGTH);
            }
        }
        coUtil.updateMilli2pixelsRatio(getWidth(), BORDER);

        if (dcop.isSizeCheckBoxSelected()) {
            drawModelBuffer(getWidth(), getHeight(), true);
        } else {
            drawModelBuffer_NO_SIZE(getWidth(), getHeight(), true);
        }
    }
    grx.drawImage(modelBuffer, coUtil.getClipL(), coUtil.getClipU(), this);

    // to do box for zoom
    if (p1 != null && p2 != null) {
        int x1 = Math.min(p1.x, p2.x);
        int y1 = Math.min(p1.y, p2.y);
        int width = Math.abs(p1.x - p2.x);
        int height = Math.abs(p1.y - p2.y);
        grx.drawRect(x1, y1, width, height);
    }
}

From source file:uk.ac.babraham.BamQC.Graphs.ScatterGraph.java

@Override
protected void paintComponent(Graphics g) {

    g.setColor(Color.WHITE);//from ww  w.  j  a va 2s.  c  om
    g.fillRect(0, 0, getWidth(), getHeight());
    g.setColor(Color.BLACK);

    if (g instanceof Graphics2D) {
        ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    }

    double yStart, xStart;
    if (minY % yInterval == 0) {
        yStart = minY;
    } else {
        yStart = yInterval * (((int) minY / yInterval) + 1);
    }

    if (minX % xInterval == 0) {
        xStart = minX;
    } else {
        xStart = xInterval * (((int) minX / xInterval) + 1);
    }

    int xOffset = 0;

    // Draw the yLabel on the left of the yAxis
    int yLabelRightShift = 12;
    if (yLabel == null || yLabel.isEmpty()) {
        yLabelRightShift = 0;
    } else {
        if (g instanceof Graphics2D) {
            Graphics2D g2 = (Graphics2D) g;
            AffineTransform orig = g2.getTransform();
            g2.rotate(-Math.PI / 2);
            g2.setColor(Color.BLACK);
            g2.drawString(yLabel, -getY(-yInterval) / 2 - (g.getFontMetrics().stringWidth(yLabel) / 2),
                    yLabelRightShift);
            g2.setTransform(orig);
        }
    }

    // Draw the y axis labels
    int lastYLabelEnd = Integer.MAX_VALUE;
    for (double i = yStart; i <= maxY; i += yInterval) {
        String label = "" + i;
        label = label.replaceAll(".0$", ""); // Don't leave trailing .0s where we don't need them.
        // Calculate the new xOffset depending on the widest ylabel.
        int width = g.getFontMetrics().stringWidth(label);
        if (width > xOffset) {
            xOffset = width;
        }
        // place the y axis labels so that they don't overlap when the plot is resized.
        int baseNumberHeight = g.getFontMetrics().getHeight();
        int baseNumberPosition = getY(i) + (baseNumberHeight / 2);
        if (baseNumberPosition + baseNumberHeight < lastYLabelEnd) {
            // Draw the y axis labels
            g.drawString(label, yLabelRightShift + 6, baseNumberPosition);
            lastYLabelEnd = baseNumberPosition + 2;
        }
    }

    // Give the x axis a bit of breathing space
    xOffset = xOffset + yLabelRightShift + 8;

    // Now draw horizontal lines across from the y axis
    g.setColor(new Color(180, 180, 180));
    for (double i = yStart; i <= maxY; i += yInterval) {
        g.drawLine(xOffset, getY(i), getWidth() - 10, getY(i));
    }
    g.setColor(Color.BLACK);

    // Draw the graph title
    int titleWidth = g.getFontMetrics().stringWidth(graphTitle);
    g.drawString(graphTitle, (xOffset + ((getWidth() - (xOffset + 10)) / 2)) - (titleWidth / 2), 30);

    // Draw the xLabel under the xAxis
    g.drawString(xLabel, (getWidth() / 2) - (g.getFontMetrics().stringWidth(xLabel) / 2), getHeight() - 5);

    // Now draw the data points
    double baseWidth = (getWidth() - (xOffset + 10)) / (maxX - minX);

    //      System.out.println("Base Width is "+baseWidth);
    // Let's find the longest label, and then work out how often we can draw labels
    int lastXLabelEnd = 0;

    // Draw the x axis labels
    for (double i = xStart; i <= maxX; i += xInterval) {
        g.setColor(Color.BLACK);
        String baseNumber = "" + i;
        baseNumber = baseNumber.replaceAll(".0$", ""); // Don't leave trailing .0s where we don't need them.
        // Calculate the new xOffset depending on the widest ylabel.
        int baseNumberWidth = g.getFontMetrics().stringWidth(baseNumber);
        int baseNumberPosition = (int) (xOffset + (baseWidth * i) - (baseNumberWidth / 2));

        if (baseNumberPosition > lastXLabelEnd) {
            g.drawString(baseNumber, baseNumberPosition, getHeight() - 25);
            lastXLabelEnd = baseNumberPosition + baseNumberWidth + 5;
        }
        // Now draw vertical lines across from the y axis
        g.setColor(new Color(180, 180, 180));
        g.drawLine((int) (xOffset + (baseWidth * i)), getHeight() - 40, (int) (xOffset + (baseWidth * i)), 40);
        g.setColor(Color.BLACK);
    }

    // Now draw the axes
    g.drawLine(xOffset, getHeight() - 40, getWidth() - 10, getHeight() - 40);
    g.drawLine(xOffset, getHeight() - 40, xOffset, 40);

    // Initialise the arrays containing the tooltips
    rectangles = new ArrayList<Rectangle>();
    tips = new ArrayList<String>();

    g.setColor(Color.BLUE);
    // Draw the data points
    double ovalSize = 5;
    // We distinguish two inputs since the x label does not start from 0.
    // used for computing the actual line points as if they were starting from 0.
    double[] inputVar = new double[data.length];
    double[] responseVar = new double[data.length];
    for (int d = 0; d < data.length; d++) {
        double x = getX(xCategories[d], xOffset) - ovalSize / 2;
        double y = getY(data[d]) - ovalSize / 2;
        g.fillOval((int) x, (int) y, (int) (ovalSize), (int) (ovalSize));
        g.drawString(toolTipLabels[d], (int) x + 2, (int) y + 16);
        inputVar[d] = Double.valueOf(xCategories[d]);
        responseVar[d] = data[d];

        // Tool tips
        Rectangle r = new Rectangle((int) x, (int) y, (int) (ovalSize), (int) (ovalSize));
        rectangles.add(r);
        tips.add(toolTipLabels[d]);
    }
    g.setColor(Color.BLACK);

    // Draw the intercept 

    // WARNING: Is drawing a least squares regression line asserting that "the distribution follows a power law" correct?
    // This is our case if we plot log-log..
    // It seems not in this paper (Appendix A) http://arxiv.org/pdf/0706.1062v2.pdf

    if (data.length > 1) {
        LinearRegression linReg = new LinearRegression(inputVar, responseVar);
        double intercept = linReg.intercept();
        double slope = linReg.slope();
        double rSquare = linReg.R2();

        // Let's now calculate the two points (x1, y1) and (xn, yn)
        // (x1, y1). We need to skip the areas where x1<minY and y1>maxY
        double x1 = minX;
        double y1 = slope * minX + intercept;
        if (y1 < minY) {
            x1 = (minY - intercept) / slope;
            y1 = minY;
        } else if (y1 > maxY) {
            x1 = (maxY - intercept) / slope;
            y1 = maxY;
        }
        // (xn, yn). maxX which essentially is inputVar[inputVar.length-1]
        double xn = maxX;
        double yn = slope * maxX + intercept;

        if (g instanceof Graphics2D) {
            ((Graphics2D) g).setStroke(new BasicStroke(1.5f));
        }
        g.setColor(Color.RED);
        g.drawLine(getX(x1, xOffset), getY(y1), getX(xn, xOffset), getY(yn));
        g.setColor(Color.BLACK);
        if (g instanceof Graphics2D) {
            ((Graphics2D) g).setStroke(new BasicStroke(1));
        }

        // Draw the legend for the intercept
        String legendString = "y = " + Precision.round(slope, 3) + "x";
        if (intercept < 0)
            legendString += " - " + Precision.round(-intercept, 3);
        else
            legendString += " + " + Precision.round(intercept, 3);
        int width = g.getFontMetrics().stringWidth(legendString);

        // First draw a box to put the legend in
        g.setColor(Color.WHITE);
        g.fillRect(xOffset + 10, 45, width + 8, 35);
        g.setColor(Color.LIGHT_GRAY);
        g.drawRect(xOffset + 10, 45, width + 8, 35);

        // Now draw the legend label
        g.setColor(Color.RED);
        g.drawString(legendString, xOffset + 13, 60);
        g.drawString("R^2 = " + Precision.round(rSquare, 3), xOffset + 13, 76);
        g.setColor(Color.BLACK);
    }

}

From source file:org.prom5.analysis.performance.dottedchart.ui.DottedChartPanel.java

/**
 * paints this log item panel and all contained log items as specified.
 * @param g the graphics object used for painting
*//*from  w ww . j a v a2 s  .  c  o m*/
public void paintComponent(Graphics grx) {
    selectedIDIndices.clear(); // for exporting
    bDrawLine = dca.getSettingPanel().isDrawLine();
    //todo
    bBottleneck = dca.getSettingPanel().isBottleneck();
    bBottleneckforInstances = dca.getSettingPanel().isBottleneckforInstance();
    double percentileL = dcModel.getOverallStatistics().getPercentile(dca.getSettingPanel().getPercentileL());
    double percentileU = dcModel.getOverallStatistics().getPercentile(dca.getSettingPanel().getPercentileU());

    Graphics gr = grx.create();

    if (this.isOpaque()) {
        gr.setColor(colorBg);
        gr.fillRect(0, 0, getWidth(), getHeight());
    }

    // paint the time indicator equipped component lane
    paintComponentLane(gr);

    // calculate are to be painted
    int height = (int) ((double) (getHeight() - (2 * border)));
    int unitHeight = height / getHashMapSize();
    int currentTop = 0;

    // paint items
    if (dcModel.getItemMap().size() > 0) {
        String key = null;
        AbstractLogUnit item = null;
        // iterate through sets
        int index = 0;
        for (Iterator itSets = dcModel.getSortedKeySetList().iterator(); itSets.hasNext();) {
            key = (String) itSets.next();
            // if key is not in instanceIDs, skip..
            if (dcModel.getTypeHashMap().equals(ST_INST) && !dcModel.getInstanceTypeToKeep().contains(key))
                continue;

            currentTop = unit2Cord(index) + unitHeight / 2;

            LogUnitList tempUnitList = new LogUnitList();
            AbstractLogUnit olditem = null;

            // for bottleneck
            boolean bInstances = false;
            boolean flag = true;
            if (dcOptionPanel.getComponentType().equals(DottedChartPanel.ST_INST) && bBottleneckforInstances) {
                LogUnitList tempUnitList2;
                tempUnitList2 = ((LogUnitList) dcModel.getItemMap().get(key));
                double percentile2L = dcModel.getTimeStatistics().get(0)
                        .getPercentile(dca.getSettingPanel().getPercentileforInstanceL());
                double percentile2U = dcModel.getTimeStatistics().get(0)
                        .getPercentile(dca.getSettingPanel().getPercentileforInstanceU());
                long tempDuration = (tempUnitList2
                        .getRightBoundaryTimestamp(dcModel.getEventTypeToKeep(),
                                dcModel.getInstanceTypeToKeep())
                        .getTime()
                        - tempUnitList2.getLeftBoundaryTimestamp(dcModel.getEventTypeToKeep(),
                                dcModel.getInstanceTypeToKeep()).getTime());
                if (dcOptionPanel.getComponentType().equals(DottedChartPanel.ST_INST) && bBottleneckforInstances
                        && tempDuration >= percentile2L && tempDuration <= percentile2U)
                    bInstances = true;
            }
            // end for bottleneck ////////

            // iterate through items
            for (Iterator itItm = ((LogUnitList) dcModel.getItemMap().get(key)).iterator(); itItm.hasNext();) {
                item = (AbstractLogUnit) itItm.next();
                if (dcModel.getEventTypeToKeep() != null
                        && (!dcModel.getEventTypeToKeep().contains(item.getType()) || !dcModel
                                .getInstanceTypeToKeep().contains(item.getProcessInstance().getName())))
                    continue;
                if (bDrawLine && item.getType().equals(dca.getSettingPanel().getStartEvent()))
                    tempUnitList.addEvent(item);
                assignColorByItem(item, gr);
                clipL = (int) gr.getClipBounds().getMinX() - 1;
                clipR = (int) gr.getClipBounds().getMaxX() + 1;
                long clipLeftTs2 = coord2timeMillis(clipL);
                long clipRightTs2 = coord2timeMillis(clipR);
                // if line is added
                if (bDrawLine && item.getType().equals(dca.getSettingPanel().getEndEvent())) {
                    for (Iterator itr = tempUnitList.iterator(); itr.hasNext();) {
                        AbstractLogUnit item2 = (AbstractLogUnit) itr.next();
                        if (item2.getElement().equals(item.getElement())
                                && item2.getProcessInstance().equals(item.getProcessInstance())) {
                            paintItemLine(time2coord(item2.getCurrentTimeStamp()) + border, currentTop,
                                    time2coord(item.getCurrentTimeStamp()) + border, gr);
                            tempUnitList.removeEvent(item2);
                            break;
                        }
                    }
                }

                // if item is not shown on the screen, ship drawing
                if (item.getCurrentTimeStamp() == null || item.getCurrentTimeStamp().getTime() < clipLeftTs2
                        || item.getCurrentTimeStamp().getTime() > clipRightTs2)
                    continue;

                // for botteleneck
                if (dcOptionPanel.getComponentType().equals(DottedChartPanel.ST_INST) && bBottleneck
                        && olditem != null
                        && (item.getCurrentTimeStamp().getTime()
                                - olditem.getCurrentTimeStamp().getTime()) >= percentileL
                        && (item.getCurrentTimeStamp().getTime()
                                - olditem.getCurrentTimeStamp().getTime()) <= percentileU) {
                    paintItemLineBottleneck(time2coord(olditem.getCurrentTimeStamp()) + border, currentTop,
                            time2coord(item.getCurrentTimeStamp()) + border, gr);
                    this.paintHighligtedItem(time2coord(olditem.getCurrentTimeStamp()) + border, currentTop, gr,
                            assignShapeByItem(olditem));
                    this.paintHighligtedItem(time2coord(item.getCurrentTimeStamp()) + border, currentTop, gr,
                            assignShapeByItem(item));
                    this.addExportingList(item);
                    olditem = item;
                    continue;
                }
                // paint an item
                if (bInstances) {
                    this.paintHighligtedItem(time2coord(item.getCurrentTimeStamp()) + border, currentTop, gr,
                            assignShapeByItem(item));
                    if (flag) {
                        this.addExportingList(item);
                        flag = false;
                    }
                } else {
                    this.paintItem(time2coord(item.getCurrentTimeStamp()) + border, currentTop, gr,
                            assignShapeByItem(item));
                }
                olditem = item;
            }
            // move y point
            index++;
        }
    }
    // to do box for zoom
    if (p1 != null && p2 != null) {
        int x1 = Math.min(p1.x, p2.x);
        int y1 = Math.min(p1.y, p2.y);
        int width = Math.abs(p1.x - p2.x);
        height = Math.abs(p1.y - p2.y);
        grx.drawRect(x1, y1, width, height);
    }
    // for exporting
    if (selectedIDIndices.size() > 0) {
        int tempArray[] = new int[selectedIDIndices.size()];
        int i = 0;
        for (Iterator itr = selectedIDIndices.iterator(); itr.hasNext();) {
            tempArray[i++] = (int) ((Integer) itr.next());
        }
        dca.setSelectedInstanceIndicesfromScreen(tempArray);
    }
}

From source file:org.processmining.analysis.performance.dottedchart.ui.DottedChartPanel.java

/**
 * paints this log item panel and all contained log items as specified.
 * /* w w  w .ja v a 2 s  .co m*/
 * @param g
 *            the graphics object used for painting
 */
public void paintComponent(Graphics grx) {
    selectedIDIndices.clear(); // for exporting
    bDrawLine = dca.getSettingPanel().isDrawLine();
    // todo
    bBottleneck = dca.getSettingPanel().isBottleneck();
    bBottleneckforInstances = dca.getSettingPanel().isBottleneckforInstance();
    double percentileL = dcModel.getOverallStatistics().getPercentile(dca.getSettingPanel().getPercentileL());
    double percentileU = dcModel.getOverallStatistics().getPercentile(dca.getSettingPanel().getPercentileU());

    Graphics gr = grx.create();

    if (this.isOpaque()) {
        gr.setColor(colorBg);
        gr.fillRect(0, 0, getWidth(), getHeight());
    }

    // paint the time indicator equipped component lane
    paintComponentLane(gr);

    // calculate are to be painted
    int height = (int) ((double) (getHeight() - (2 * border)));
    int unitHeight = height / getHashMapSize();
    int currentTop = 0;

    // paint items
    if (dcModel.getItemMap().size() > 0) {
        String key = null;
        AbstractLogUnit item = null;
        // iterate through sets
        int index = 0;
        for (Iterator itSets = dcModel.getSortedKeySetList().iterator(); itSets.hasNext();) {
            key = (String) itSets.next();
            // if key is not in instanceIDs, skip..
            if (dcModel.getTypeHashMap().equals(ST_INST) && !dcModel.getInstanceTypeToKeep().contains(key))
                continue;

            currentTop = unit2Cord(index) + unitHeight / 2;

            LogUnitList tempUnitList = new LogUnitList();
            AbstractLogUnit olditem = null;

            // for bottleneck
            boolean bInstances = false;
            boolean flag = true;
            if (dcOptionPanel.getComponentType().equals(DottedChartPanel.ST_INST) && bBottleneckforInstances) {
                LogUnitList tempUnitList2;
                tempUnitList2 = ((LogUnitList) dcModel.getItemMap().get(key));
                double percentile2L = dcModel.getTimeStatistics().get(0)
                        .getPercentile(dca.getSettingPanel().getPercentileforInstanceL());
                double percentile2U = dcModel.getTimeStatistics().get(0)
                        .getPercentile(dca.getSettingPanel().getPercentileforInstanceU());
                long tempDuration = (tempUnitList2
                        .getRightBoundaryTimestamp(dcModel.getEventTypeToKeep(),
                                dcModel.getInstanceTypeToKeep())
                        .getTime()
                        - tempUnitList2.getLeftBoundaryTimestamp(dcModel.getEventTypeToKeep(),
                                dcModel.getInstanceTypeToKeep()).getTime());
                if (dcOptionPanel.getComponentType().equals(DottedChartPanel.ST_INST) && bBottleneckforInstances
                        && tempDuration >= percentile2L && tempDuration <= percentile2U)
                    bInstances = true;
            }
            // end for bottleneck ////////

            // iterate through items
            for (Iterator itItm = ((LogUnitList) dcModel.getItemMap().get(key)).iterator(); itItm.hasNext();) {
                item = (AbstractLogUnit) itItm.next();
                if (dcModel.getEventTypeToKeep() != null
                        && (!dcModel.getEventTypeToKeep().contains(item.getType()) || !dcModel
                                .getInstanceTypeToKeep().contains(item.getProcessInstance().getName())))
                    continue;
                if (bDrawLine && item.getType().equals(dca.getSettingPanel().getStartEvent()))
                    tempUnitList.addEvent(item);
                assignColorByItem(item, gr);
                clipL = (int) gr.getClipBounds().getMinX() - 1;
                clipR = (int) gr.getClipBounds().getMaxX() + 1;
                long clipLeftTs2 = coord2timeMillis(clipL);
                long clipRightTs2 = coord2timeMillis(clipR);
                // if line is added
                if (bDrawLine && item.getType().equals(dca.getSettingPanel().getEndEvent())) {
                    for (Iterator itr = tempUnitList.iterator(); itr.hasNext();) {
                        AbstractLogUnit item2 = (AbstractLogUnit) itr.next();
                        if (item2.getElement().equals(item.getElement())
                                && item2.getProcessInstance().equals(item.getProcessInstance())) {
                            paintItemLine(time2coord(item2.getCurrentTimeStamp()) + border, currentTop,
                                    time2coord(item.getCurrentTimeStamp()) + border, gr);
                            tempUnitList.removeEvent(item2);
                            break;
                        }
                    }
                }

                // if item is not shown on the screen, ship drawing
                if (item.getCurrentTimeStamp() == null || item.getCurrentTimeStamp().getTime() < clipLeftTs2
                        || item.getCurrentTimeStamp().getTime() > clipRightTs2)
                    continue;

                // for botteleneck
                if (dcOptionPanel.getComponentType().equals(DottedChartPanel.ST_INST) && bBottleneck
                        && olditem != null
                        && (item.getCurrentTimeStamp().getTime()
                                - olditem.getCurrentTimeStamp().getTime()) >= percentileL
                        && (item.getCurrentTimeStamp().getTime()
                                - olditem.getCurrentTimeStamp().getTime()) <= percentileU) {
                    paintItemLineBottleneck(time2coord(olditem.getCurrentTimeStamp()) + border, currentTop,
                            time2coord(item.getCurrentTimeStamp()) + border, gr);
                    this.paintHighligtedItem(time2coord(olditem.getCurrentTimeStamp()) + border, currentTop, gr,
                            assignShapeByItem(olditem));
                    this.paintHighligtedItem(time2coord(item.getCurrentTimeStamp()) + border, currentTop, gr,
                            assignShapeByItem(item));
                    this.addExportingList(item);
                    olditem = item;
                    continue;
                }
                // paint an item
                if (bInstances) {
                    this.paintHighligtedItem(time2coord(item.getCurrentTimeStamp()) + border, currentTop, gr,
                            assignShapeByItem(item));
                    if (flag) {
                        this.addExportingList(item);
                        flag = false;
                    }
                } else {
                    this.paintItem(time2coord(item.getCurrentTimeStamp()) + border, currentTop, gr,
                            assignShapeByItem(item));
                }
                olditem = item;
            }
            // move y point
            index++;
        }
    }
    // to do box for zoom
    if (p1 != null && p2 != null) {
        int x1 = Math.min(p1.x, p2.x);
        int y1 = Math.min(p1.y, p2.y);
        int width = Math.abs(p1.x - p2.x);
        height = Math.abs(p1.y - p2.y);
        grx.drawRect(x1, y1, width, height);
    }
    // for exporting
    if (selectedIDIndices.size() > 0) {
        int tempArray[] = new int[selectedIDIndices.size()];
        int i = 0;
        for (Iterator itr = selectedIDIndices.iterator(); itr.hasNext();) {
            tempArray[i++] = (int) ((Integer) itr.next());
        }
        dca.setSelectedInstanceIndicesfromScreen(tempArray);
    }
}

From source file:com.lfv.lanzius.server.WorkspaceView.java

@Override
protected void paintComponent(Graphics g) {
    int w = getWidth();
    int h = getHeight();

    Document doc = server.getDocument();

    Color storedCol = g.getColor();
    Font storedFont = g.getFont();

    // Fill workspace area
    g.setColor(getBackground());/*ww  w  .ja  v  a  2s  .co  m*/
    g.fillRect(0, 0, w, h);

    // Should the cached version be updated?
    int updateDocumentVersion = server.getDocumentVersion();
    boolean update = (documentVersion != updateDocumentVersion);

    // Check if we have cached the latest document version, otherwise cache the terminals
    if (update) {
        log.debug("Updating view to version " + updateDocumentVersion);
        terminalMap.clear();
        groupList.clear();
        if (doc != null) {
            synchronized (doc) {

                // Clear the visible attribute on all groups
                // except the started or paused ones
                Element egd = doc.getRootElement().getChild("GroupDefs");
                Iterator iter = egd.getChildren().iterator();
                while (iter.hasNext()) {
                    Element eg = (Element) iter.next();
                    boolean isVisible = !DomTools.getAttributeString(eg, "state", "stopped", false)
                            .equals("stopped");
                    eg.setAttribute("visible", String.valueOf(isVisible));
                }

                // Gather information about terminals and cache it
                Element etd = doc.getRootElement().getChild("TerminalDefs");
                iter = etd.getChildren().iterator();
                while (iter.hasNext()) {
                    Element et = (Element) iter.next();
                    int tid = DomTools.getAttributeInt(et, "id", 0, false);
                    if (tid > 0) {
                        // Create terminal and add it to list
                        Terminal t = new Terminal(tid, DomTools.getAttributeInt(et, "x", 0, false),
                                DomTools.getAttributeInt(et, "y", 0, false),
                                DomTools.getChildText(et, "Name", "T/" + tid, false),
                                DomTools.getAttributeBoolean(et, "online", false, false),
                                DomTools.getAttributeBoolean(et, "selected", false, false));
                        terminalMap.put(tid, t);

                        // Is the terminal monitored?
                        t.isMonitored = DomTools.getAttributeBoolean(et, "monitored", false, false);

                        // Examine the Player element under PlayerSetup
                        t.groupColor = null;
                        Element ep = DomTools.getElementFromSection(doc, "PlayerSetup", "terminalid",
                                String.valueOf(tid));

                        // Has linked player for this terminal
                        if (ep != null) {
                            StringBuffer sb = new StringBuffer();

                            // Append player name
                            sb.append(DomTools.getChildText(ep, "Name", "P/?", true));
                            sb.append(" (");

                            // Append role list
                            boolean hasRoles = false;
                            Element ers = ep.getChild("RoleSetup");
                            if (ers != null) {
                                Iterator iterr = ers.getChildren().iterator();

                                while (iterr.hasNext()) {
                                    Element er = (Element) iterr.next();
                                    String id = er.getAttributeValue("id");
                                    er = DomTools.getElementFromSection(doc, "RoleDefs", "id", id);
                                    if (er != null) {
                                        sb.append(DomTools.getChildText(er, "Name", "R/" + id, false));
                                        sb.append(", ");
                                        hasRoles = true;
                                    }
                                }
                                if (hasRoles) {
                                    // Trim last comma
                                    int len = sb.length();
                                    sb.setLength(Math.max(len - 2, 0));
                                }
                                sb.append(")");
                            }
                            t.roles = sb.toString();

                            // Is the player relocated?
                            t.isRelocated = DomTools.getAttributeBoolean(ep, "relocated", false, false);

                            // Get group name and color
                            Element eg = DomTools.getElementFromSection(doc, "GroupDefs", "id",
                                    DomTools.getAttributeString(ep, "groupid", "0", true));
                            t.groupColor = Color.lightGray;
                            if (eg != null) {
                                String sc = DomTools.getChildText(eg, "Color", null, false);
                                if (sc != null) {
                                    try {
                                        t.groupColor = Color.decode(sc);
                                    } catch (NumberFormatException ex) {
                                        log.warn("Invalid color attribute on Group node, defaulting to grey");
                                    }
                                }
                                //t.name += "  "+DomTools.getChildText(eg, "Name", "G/"+eg.getAttributeValue("id"), false);
                                t.groupName = DomTools.getChildText(eg, "Name",
                                        "G/" + eg.getAttributeValue("id"), false);

                                // This group should now be visible
                                eg.setAttribute("visible", "true");
                            } else
                                log.warn("Invalid groupid attribute on Player node, defaulting to grey");
                        }
                    } else
                        log.error("Invalid id attribute on Terminal node, skipping");
                }

                // Gather information about groups and cache it
                iter = egd.getChildren().iterator();
                while (iter.hasNext()) {
                    Element eg = (Element) iter.next();
                    if (DomTools.getAttributeBoolean(eg, "visible", false, false)) {
                        int gid = DomTools.getAttributeInt(eg, "id", 0, true);
                        if (gid > 0) {
                            Group grp = new Group(gid, DomTools.getChildText(eg, "Name", "G/" + gid, false),
                                    DomTools.getAttributeBoolean(eg, "selected", false, false));
                            groupList.add(grp);

                            // group color
                            String sc = DomTools.getChildText(eg, "Color", null, false);
                            if (sc != null) {
                                try {
                                    grp.color = Color.decode(sc);
                                } catch (NumberFormatException ex) {
                                    log.warn("Invalid color attribute on Group node, defaulting to grey");
                                }
                            }

                            // state color
                            grp.stateColor = Color.red;
                            String state = DomTools.getAttributeString(eg, "state", "stopped", false);
                            if (state.equals("started"))
                                grp.stateColor = Color.green;
                            else if (state.equals("paused"))
                                grp.stateColor = Color.orange;
                        }
                    }
                }
            }
        }
    }

    if (doc == null) {
        g.setColor(Color.black);
        String text = "No configuration loaded. Select 'Load configuration...' from the file menu.";
        g.drawString(text, (w - SwingUtilities.computeStringWidth(g.getFontMetrics(), text)) / 2, h * 5 / 12);
    } else {
        g.setFont(new Font("Dialog", Font.BOLD, 13));

        Iterator<Terminal> itert = terminalMap.values().iterator();
        while (itert.hasNext()) {
            Terminal t = itert.next();

            // Draw box
            int b = t.isSelected ? SERVERVIEW_SELECTION_BORDER : 1;
            g.setColor(Color.black);
            g.fillRect(t.x + SERVERVIEW_SELECTION_BORDER - b, t.y + SERVERVIEW_SELECTION_BORDER - b,
                    SERVERVIEW_TERMINAL_WIDTH + 2 * b, SERVERVIEW_TERMINAL_HEIGHT + 2 * b);
            g.setColor(t.groupColor == null ? Color.white : t.groupColor);
            g.fillRect(t.x + SERVERVIEW_SELECTION_BORDER, t.y + SERVERVIEW_SELECTION_BORDER,
                    SERVERVIEW_TERMINAL_WIDTH, SERVERVIEW_TERMINAL_HEIGHT);

            // Inner areas
            Rectangle r = new Rectangle(t.x + SERVERVIEW_SELECTION_BORDER + SERVERVIEW_TERMINAL_BORDER,
                    t.y + SERVERVIEW_SELECTION_BORDER + SERVERVIEW_TERMINAL_BORDER,
                    SERVERVIEW_TERMINAL_WIDTH - 2 * SERVERVIEW_TERMINAL_BORDER,
                    g.getFontMetrics().getHeight() + 4);

            g.setColor(Color.white);
            g.fillRect(r.x, r.y, r.width, r.height);
            g.fillRect(r.x, r.y + r.height + SERVERVIEW_TERMINAL_BORDER + 2, r.width,
                    SERVERVIEW_TERMINAL_HEIGHT - 3 * SERVERVIEW_TERMINAL_BORDER - r.height - 2);
            g.setColor(Color.black);
            g.drawRect(r.x, r.y, r.width, r.height);
            g.drawRect(r.x, r.y + r.height + SERVERVIEW_TERMINAL_BORDER + 2, r.width,
                    SERVERVIEW_TERMINAL_HEIGHT - 3 * SERVERVIEW_TERMINAL_BORDER - r.height - 2);

            // Name of terminal and group
            if (server.isaClient(t.tid)) {
                g.drawImage(indicatorIsa.getImage(), r.x + r.width - 20, r.y + SERVERVIEW_TERMINAL_HEIGHT - 26,
                        null);
            }
            g.drawString(t.name + " " + t.groupName, r.x + 4, r.y + r.height - 4);

            double px = r.x + 4;
            double py = r.y + r.height + SERVERVIEW_TERMINAL_BORDER + 5;

            // Draw monitored indicator
            if (t.isMonitored) {
                g.drawImage(indicatorMonitored.getImage(), r.x + r.width - 9, r.y + 3, null);
            }

            // Draw relocated indicator
            if (t.isRelocated) {
                g.drawImage(indicatorRelocated.getImage(), r.x + r.width - 9, r.y + 13, null);
            }

            // Draw online indicator
            r.setBounds(r.x, r.y + r.height, r.width, 3);
            g.setColor(t.isOnline ? Color.green : Color.red);
            g.fillRect(r.x, r.y, r.width, r.height);
            g.setColor(Color.black);
            g.drawRect(r.x, r.y, r.width, r.height);

            // Roles
            if (t.roles.length() > 0) {
                LineBreakMeasurer lbm = new LineBreakMeasurer(new AttributedString(t.roles).getIterator(),
                        new FontRenderContext(null, false, true));

                TextLayout layout;
                while ((layout = lbm
                        .nextLayout(SERVERVIEW_TERMINAL_WIDTH - 2 * SERVERVIEW_TERMINAL_BORDER)) != null) {
                    if (py < t.y + SERVERVIEW_TERMINAL_HEIGHT) {
                        py += layout.getAscent();
                        layout.draw((Graphics2D) g, (int) px, (int) py);
                        py += layout.getDescent() + layout.getLeading();
                    }
                }
            }
        }

        // Draw group indicators
        int nbrGroupsInRow = w
                / (2 * Constants.SERVERVIEW_SELECTION_BORDER + 2 + Constants.SERVERVIEW_GROUP_WIDTH);
        if (nbrGroupsInRow < 1)
            nbrGroupsInRow = 1;
        int nbrGroupRows = (groupList.size() + nbrGroupsInRow - 1) / nbrGroupsInRow;

        int innerWidth = Constants.SERVERVIEW_GROUP_WIDTH;
        int innerHeight = g.getFontMetrics().getHeight() + 5;

        int outerWidth = innerWidth + 2 * Constants.SERVERVIEW_SELECTION_BORDER + 2;
        int outerHeight = innerHeight + 2 * Constants.SERVERVIEW_SELECTION_BORDER + 2;

        int x = 0;
        int y = h - outerHeight * nbrGroupRows;

        g.setColor(Color.white);
        g.fillRect(0, y, w, h - y);
        g.setColor(Color.black);
        g.drawLine(0, y - 1, w - 1, y - 1);

        Iterator<Group> iterg = groupList.iterator();
        while (iterg.hasNext()) {
            Group grp = iterg.next();

            // Group box
            grp.boundingRect.setBounds(x, y, outerWidth, outerHeight);
            int b = grp.isSelected ? Constants.SERVERVIEW_SELECTION_BORDER : 1;
            g.setColor(Color.black);
            g.fillRect(x + Constants.SERVERVIEW_SELECTION_BORDER - b + 1,
                    y + Constants.SERVERVIEW_SELECTION_BORDER - b + 1, innerWidth + 2 * b, innerHeight + 2 * b);
            g.setColor(grp.color);
            g.fillRect(x + Constants.SERVERVIEW_SELECTION_BORDER + 1,
                    y + Constants.SERVERVIEW_SELECTION_BORDER + 1, innerWidth, innerHeight);

            g.setColor(Color.black);
            g.drawString(grp.name, x + Constants.SERVERVIEW_SELECTION_BORDER + 4,
                    y + Constants.SERVERVIEW_SELECTION_BORDER + innerHeight - 4 + 1);

            // Draw started indicator
            g.setColor(grp.stateColor);
            g.fillRect(x + Constants.SERVERVIEW_SELECTION_BORDER + 1,
                    y + Constants.SERVERVIEW_SELECTION_BORDER + 1, innerWidth, 2);
            g.setColor(Color.black);
            g.drawLine(x + Constants.SERVERVIEW_SELECTION_BORDER + 1,
                    y + Constants.SERVERVIEW_SELECTION_BORDER + 3,
                    x + Constants.SERVERVIEW_SELECTION_BORDER + 1 + innerWidth,
                    y + Constants.SERVERVIEW_SELECTION_BORDER + 3);

            x += outerWidth;
            if ((x + outerWidth) > w) {
                x = 0;
                y += outerHeight;
            }
        }
    }

    // Store cached version
    documentVersion = updateDocumentVersion;

    g.setColor(storedCol);
    g.setFont(storedFont);
}

From source file:ucar.unidata.idv.ui.ImageGenerator.java

/**
 * Process the image/*  w  w  w  .  jav a2  s  .com*/
 *
 * @param image The image
 * @param filename File to write the image to
 * @param node Node to process
 * @param props Extra properties
 * @param viewManager The viewmanager this image came from
 * @param imageProps  the image properties
 *
 *
 * @return The processed image
 * @throws Throwable On badness
 */
protected BufferedImage processImage(BufferedImage image, String filename, Element node, Hashtable props,
        ViewManager viewManager, Hashtable imageProps) throws Throwable {

    if (node == null) {
        return image;
    }

    if (props == null) {
        props = new Hashtable();
    }
    if (viewManager != null) {
        Animation animation = viewManager.getAnimation();
        props.put(PROP_ANIMATIONTIME, "");
        if (animation != null) {
            if (animation.getAniValue() != null) {
                props.put(PROP_ANIMATIONTIME, animation.getAniValue());
            }
        }
    }
    getProperties().putAll(props);

    NodeList elements = XmlUtil.getElements(node);
    Hashtable seenColorTable = new Hashtable();
    for (int childIdx = 0; childIdx < elements.getLength(); childIdx++) {
        boolean shouldIterateChildren = true;
        BufferedImage newImage = null;
        int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
        Element child = (Element) elements.item(childIdx);
        String tagName = child.getTagName();

        if (tagName.equals(TAG_RESIZE)) {
            newImage = ImageUtils.toBufferedImage(resize(image, child));
        } else if (tagName.equals(TAG_FILESET)) {
            //ignore
        } else if (tagName.equals(TAG_OUTPUT)) {
            processTagOutput(child);
        } else if (tagName.equals(TAG_DISPLAYLIST)) {
            if (viewManager != null) {
                newImage = ImageUtils.toBufferedImage(image, true);
                Graphics g = newImage.getGraphics();
                String valign = applyMacros(child, ATTR_VALIGN, VALUE_BOTTOM);
                Font font = getFont(child);
                if (XmlUtil.hasAttribute(child, ATTR_MATTEBG)) {
                    int height = viewManager.paintDisplayList((Graphics2D) g, null, imageWidth, imageHeight,
                            valign.equals(VALUE_BOTTOM), null, font);

                    int top = (valign.equals(VALUE_TOP) ? height : 0);
                    int bottom = (valign.equals(VALUE_BOTTOM) ? height : 0);
                    newImage = ImageUtils.matte(image, top, bottom, 0, 0,
                            applyMacros(child, ATTR_MATTEBG, Color.white));
                    g = newImage.getGraphics();
                    imageHeight += height;
                }

                Color c = applyMacros(child, ATTR_COLOR, (Color) null);
                viewManager.paintDisplayList((Graphics2D) g, null, imageWidth, imageHeight,
                        valign.equals(VALUE_BOTTOM), c, font);
            }
        } else if (tagName.equals(TAG_COLORBAR) || tagName.equals(TAG_KML_COLORBAR)) {
            // only do one colorbar if we are writing to kml
            Integer index = (Integer) props.get(PROP_IMAGEINDEX);
            if ((index != null) && (index.intValue() > 0) && tagName.equals(TAG_KML_COLORBAR)) {
                continue;
            }

            boolean showLines = applyMacros(child, ATTR_SHOWLINES, false);

            List<DisplayControlImpl> controls = (List<DisplayControlImpl>) ((viewManager != null)
                    ? viewManager.getControls()
                    : new ArrayList());

            if (XmlUtil.hasAttribute(child, ATTR_DISPLAY)) {
                DisplayControlImpl display = ((controls.size() > 0)
                        ? findDisplayControl(XmlUtil.getAttribute(child, ATTR_DISPLAY), controls)
                        : findDisplayControl(child));
                if (display == null) {
                    error("Could not find display:" + XmlUtil.toString(node));
                    return null;
                }
                controls = Misc.newList(display);
            }

            int width = applyMacros(child, ATTR_WIDTH, 150);
            int height = applyMacros(child, ATTR_HEIGHT, 20);
            int ticks = applyMacros(child, ATTR_TICKMARKS, 0);
            double interval = applyMacros(child, ATTR_INTERVAL, -1.0);
            String valuesStr = applyMacros(child, ATTR_VALUES, (String) null);
            Color c = applyMacros(child, ATTR_COLOR, Color.black);

            Color lineColor = applyMacros(child, ATTR_LINECOLOR, c);

            Rectangle imageRect = new Rectangle(0, 0, imageWidth, imageHeight);

            Point pp = ImageUtils.parsePoint(applyMacros(child, ATTR_PLACE, "ll,10,-10"), imageRect);
            Point ap = ImageUtils.parsePoint(applyMacros(child, ATTR_ANCHOR, "ll"),
                    new Rectangle(0, 0, width, height));

            String orientation = applyMacros(child, ATTR_ORIENTATION, VALUE_BOTTOM);
            boolean vertical = orientation.equals(VALUE_RIGHT) || orientation.equals(VALUE_LEFT);
            int baseY = pp.y - ap.y + (vertical ? 0 : height);
            int baseX = pp.x - ap.x;

            List colorTables = new ArrayList();
            List ranges = new ArrayList();
            List units = new ArrayList();

            boolean forKml = tagName.equals(TAG_KML_COLORBAR);

            for (int i = 0; i < controls.size(); i++) {
                DisplayControlImpl control = (DisplayControlImpl) controls.get(i);
                ColorTable colorTable = control.getColorTable();
                if (colorTable == null) {
                    continue;
                }
                Range range = control.getRangeForColorTable();
                //only do unique color tables
                Object[] key = { colorTable, range };
                if (seenColorTable.get(key) != null) {
                    continue;
                }
                seenColorTable.put(key, key);
                colorTables.add(colorTable);
                ranges.add(range);
                units.add(control.getDisplayUnit());
            }

            for (int i = 0; i < colorTables.size(); i++) {
                ColorTable colorTable = (ColorTable) colorTables.get(i);
                Range range = (Range) ranges.get(i);
                Unit unit = (Unit) units.get(i);
                Image imageToDrawIn;
                if (forKml) {
                    if (vertical) {
                        baseX = 0;
                        baseY = 0;
                    } else {
                        baseX = 0;
                        baseY = height;
                    }
                    int space = applyMacros(child, ATTR_SPACE, (vertical ? width : height));
                    imageToDrawIn = new BufferedImage(width + (vertical ? space : 0),
                            height + (vertical ? 0 : space), BufferedImage.TYPE_INT_RGB);
                } else {
                    imageToDrawIn = newImage = ImageUtils.toBufferedImage(image);
                }
                Graphics g = imageToDrawIn.getGraphics();
                if (forKml) {
                    Color bgColor = applyMacros(child, ATTR_BACKGROUND, Color.white);
                    g.setColor(bgColor);
                    g.fillRect(0, 0, imageToDrawIn.getWidth(null), imageToDrawIn.getHeight(null));
                }
                boolean includeAlpha = applyMacros(child, ATTR_TRANSPARENCY, true);

                float[][] ctValues;

                if (includeAlpha) {
                    ctValues = colorTable.getAlphaTable();
                } else {
                    ctValues = colorTable.getNonAlphaTable();
                }
                ColorMap colorMap = new BaseRGBMap(ctValues);
                ColorPreview preview = new ColorPreview(colorMap, (vertical ? width : height));
                if (vertical) {
                    preview.setSize(new Dimension(height, width));
                } else {
                    preview.setSize(new Dimension(width, height));
                }
                Image previewImage = ColorTableCanvas.getImage(colorTable, (vertical ? height : width),
                        (vertical ? width : height), includeAlpha);

                if (vertical) {
                    int imageType = includeAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;

                    BufferedImage tmpImage = new BufferedImage(width, height, imageType);

                    Graphics2D tmpG = (Graphics2D) tmpImage.getGraphics();
                    tmpG.rotate(Math.toRadians(90.0));
                    tmpG.drawImage(previewImage, 0, 0 - width, null);
                    previewImage = tmpImage;
                }
                if (forKml) {
                    g.drawImage(previewImage, 0, 0, null);
                } else {
                    g.drawImage(previewImage, baseX, (vertical ? baseY : baseY - height), null);
                }
                if (showLines) {
                    g.setColor(lineColor);
                    g.drawRect(baseX, (vertical ? baseY : baseY - height), width - 1,
                            height - (vertical ? 1 : 0));
                }
                setFont(g, child);
                FontMetrics fm = g.getFontMetrics();
                List values = new ArrayList();
                String suffixFrequency = XmlUtil.getAttribute(child, ATTR_SUFFIXFREQUENCY,
                        XmlUtil.getAttribute(child, ATTR_SHOWUNIT, "false")).toLowerCase();
                String unitDefault = (!suffixFrequency.equals("false")) ? " %unit%" : "";
                String labelSuffix = applyMacros(child, ATTR_SUFFIX, unitDefault);
                if (unit != null) {
                    labelSuffix = labelSuffix.replace("%unit%", "" + unit);
                } else {
                    labelSuffix = labelSuffix.replace("%unit%", "");
                }
                if (valuesStr != null) {
                    double[] valueArray = Misc.parseDoubles(valuesStr, ",");
                    for (int valueIdx = 0; valueIdx < valueArray.length; valueIdx++) {
                        values.add(new Double(valueArray[valueIdx]));
                    }
                } else if (ticks > 0) {
                    int spacing = ((ticks == 1) ? 0 : (vertical ? height : width) / (ticks - 1));
                    for (int tickIdx = 0; tickIdx < ticks; tickIdx++) {
                        double percent = ((ticks > 1) ? (double) tickIdx / (double) (ticks - 1) : 0.0);
                        values.add(new Double(range.getValueOfPercent(percent)));
                    }
                } else if (interval > 0) {
                    double value = range.getMin();
                    double max = range.getMax();
                    while (value <= max) {
                        values.add(new Double(value));
                        value += interval;
                    }
                }
                for (int valueIdx = 0; valueIdx < values.size(); valueIdx++) {
                    double value = ((Double) values.get(valueIdx)).doubleValue();
                    int x;
                    int y;
                    if (vertical) {
                        if (orientation.equals(VALUE_RIGHT)) {
                            x = baseX + width;
                        } else {
                            x = baseX;
                        }
                        y = baseY + (int) (range.getPercent(value) * height);
                        if (y > baseY + height) {
                            break;
                        }
                    } else {
                        if (orientation.equals(VALUE_BOTTOM)) {
                            y = baseY;
                        } else {
                            y = baseY - height;
                        }

                        if (range != null) {
                            x = baseX + (int) (range.getPercent(value) * width);
                        } else {
                            x = baseX;
                        }

                        if (x > baseX + width) {
                            break;
                        }
                    }
                    String tickLabel = getIdv().getDisplayConventions().format(value);
                    if (suffixFrequency.equals(VALUE_LAST) && (valueIdx == values.size() - 1)) {
                        tickLabel += labelSuffix;
                    } else if (suffixFrequency.equals(VALUE_FIRST) && (valueIdx == 0)) {
                        tickLabel += labelSuffix;
                    } else if (suffixFrequency.equals(VALUE_ALL) || suffixFrequency.equals("true")) {
                        tickLabel += labelSuffix;
                    }

                    Rectangle2D rect = fm.getStringBounds(tickLabel, g);
                    g.setColor(lineColor);
                    if (orientation.equals(VALUE_RIGHT)) {
                        g.drawLine(x + 1, y, x, y);
                        if (showLines) {
                            g.drawLine(x, y, x - width, y);
                        }
                    } else if (orientation.equals(VALUE_LEFT)) {
                        g.drawLine(x - 1, y, x, y);
                        if (showLines) {
                            g.drawLine(x, y, x + width, y);
                        }
                    } else if (orientation.equals(VALUE_BOTTOM)) {
                        g.drawLine(x, y + 1, x, y);
                        if (showLines) {
                            g.drawLine(x, y, x, y - height);
                        }
                    } else {
                        g.drawLine(x, y - 1, x, y);
                        if (showLines) {
                            g.drawLine(x, y, x, y + height);
                        }
                    }
                    g.setColor(c);
                    if (orientation.equals(VALUE_RIGHT)) {
                        int yLoc = y + (int) (rect.getHeight() / 2) - 2;
                        if (forKml) {
                            if (valueIdx == 0) {
                                yLoc = y + (int) (rect.getHeight()) - 2;
                            } else if (valueIdx == values.size() - 1) {
                                yLoc = y - (int) (rect.getHeight()) + 6;
                            }
                        }
                        g.drawString(tickLabel, x + 2, yLoc);
                    } else if (orientation.equals(VALUE_LEFT)) {
                        int xLoc = x - 2 - (int) rect.getWidth();
                        g.drawString(tickLabel, xLoc, y + (int) (rect.getHeight() / 2) - 2);
                    } else if (orientation.equals(VALUE_BOTTOM)) {
                        int xLoc = x - (int) (rect.getWidth() / 2);
                        if (forKml) {
                            if (valueIdx == 0) {
                                xLoc = x + 2;
                            } else if (valueIdx == values.size() - 1) {
                                xLoc = x - (int) rect.getWidth() + 2;
                            }
                        }
                        g.drawString(tickLabel, xLoc, y + (int) rect.getHeight() + 2);
                    } else {
                        g.drawString(tickLabel, x - (int) (rect.getWidth() / 2), y - 2);
                    }
                }
                if (vertical) {
                    baseX += width + 30;
                } else {
                    baseY += height + 30;
                }
                if (forKml) {
                    String tmpImageFile = applyMacros(child, ATTR_FILE,
                            getIdv().getStore().getTmpFile("testcolorbar${viewindex}.png"));
                    String template = "<ScreenOverlay><name>${kml.name}</name><Icon><href>${icon}</href></Icon>\n"
                            + "<overlayXY x=\"${kml.overlayXY.x}\" y=\"${kml.overlayXY.y}\" xunits=\"${kml.overlayXY.xunits}\" yunits=\"${kml.overlayXY.yunits}\"/>\n"
                            + "<screenXY x=\"${kml.screenXY.x}\" y=\"${kml.screenXY.y}\" xunits=\"${kml.screenXY.xunits}\" yunits=\"${kml.screenXY.yunits}\"/>\n"
                            + "<size x=\"${kml.size.x}\" y=\"${kml.size.y}\" xunits=\"${kml.size.xunits}\" yunits=\"${kml.size.yunits}\"/>\n"
                            + "</ScreenOverlay>\n";
                    String[] macros = { "kml.name", "kml.overlayXY.x", "kml.overlayXY.y",
                            "kml.overlayXY.xunits", "kml.overlayXY.yunits", "kml.screenXY.x", "kml.screenXY.y",
                            "kml.screenXY.xunits", "kml.screenXY.yunits", "kml.size.x", "kml.size.y",
                            "kml.size.xunits", "kml.size.yunits" };
                    String[] macroValues = { "", "0", "1", "fraction", "fraction", "0", "1", "fraction",
                            "fraction", "-1", "-1", "pixels", "pixels" };

                    for (int macroIdx = 0; macroIdx < macros.length; macroIdx++) {
                        template = template.replace("${" + macros[macroIdx] + "}",
                                applyMacros(child, macros[macroIdx], macroValues[macroIdx]));
                    }
                    template = template.replace("${icon}", IOUtil.getFileTail(tmpImageFile));
                    imageProps.put("kml", template);
                    List kmlFiles = (List) imageProps.get("kmlfiles");
                    //TODO: Only do the first one for now
                    if (kmlFiles == null) {
                        kmlFiles = new ArrayList();
                        imageProps.put("kmlfiles", kmlFiles);
                    }
                    kmlFiles.add(tmpImageFile);

                    //                        System.out.println(template);
                    ImageUtils.writeImageToFile(imageToDrawIn, tmpImageFile);
                }
            }

        } else if (tagName.equals(TAG_TRANSPARENT) || tagName.equals(TAG_BGTRANSPARENT)) {
            Color c = null;
            if (tagName.equals(TAG_BGTRANSPARENT)) {
                c = viewManager.getBackground();
            } else {
                c = applyMacros(child, ATTR_COLOR, (Color) null);
            }
            //                System.err.println ("c:" + c);
            int[] redRange = { 0, 0 };
            int[] greenRange = { 0, 0 };
            int[] blueRange = { 0, 0 };
            if (c != null) {
                //                    System.err.println("got color");
                redRange[0] = redRange[1] = c.getRed();
                greenRange[0] = greenRange[1] = c.getGreen();
                blueRange[0] = blueRange[1] = c.getBlue();
            } else {
            }
            newImage = ImageUtils.makeColorTransparent(image, redRange, greenRange, blueRange);
        } else if (tagName.equals(TAG_SHOW)) {
            JComponent contents = new JLabel(new ImageIcon(image));
            String message = applyMacros(child, ATTR_MESSAGE, (String) null);
            if (message != null) {
                contents = GuiUtils.topCenter(new JLabel(message), contents);
            }
            if (!GuiUtils.askOkCancel("Continue?", contents)) {
                throw new MyQuitException();
            }
        } else if (tagName.equals(TAG_MATTE)) {
            newImage = doMatte(image, child, 0);
        } else if (tagName.equals(TAG_LATLONLABELS)) {
            newImage = doLatLonLabels(child, viewManager, image, imageProps);
        } else if (tagName.equals(TAG_WRITE)) {
            ImageUtils.writeImageToFile(image, getImageFileName(applyMacros(child, ATTR_FILE)));

        } else if (tagName.equals(TAG_PUBLISH)) {
            getIdv().getPublishManager().publishIslImage(this, node, image);
        } else if (tagName.equals(TAG_CLIP)) {
            int[] ul;
            int[] lr;
            if (XmlUtil.hasAttribute(child, ATTR_DISPLAY)) {
                //                    System.err.println("Clipping from display");
                DisplayControlImpl dc = findDisplayControl(child);
                if (dc == null) {
                    throw new IllegalArgumentException("Could not find display:" + XmlUtil.toString(node));
                }
                NavigatedDisplay display = (NavigatedDisplay) viewManager.getMaster();
                MapProjection mapProjection = dc.getDataProjection();
                java.awt.geom.Rectangle2D rect = mapProjection.getDefaultMapArea();
                LatLonPoint llplr = mapProjection.getLatLon(new double[][] { { rect.getX() + rect.getWidth() },
                        { rect.getY() + rect.getHeight() } });
                LatLonPoint llpul = mapProjection
                        .getLatLon(new double[][] { { rect.getX() }, { rect.getY() } });
                EarthLocation ulEl = new EarthLocationTuple(llpul, new Real(RealType.Altitude, 0));
                EarthLocation lrEl = new EarthLocationTuple(llplr, new Real(RealType.Altitude, 0));
                ul = display.getScreenCoordinates(display.getSpatialCoordinates(ulEl, null));
                lr = display.getScreenCoordinates(display.getSpatialCoordinates(lrEl, null));
                //System.err.println("ul:" + ulEl + " lr:" + lrEl);
                if (ul[0] > lr[0]) {
                    int tmp = ul[0];
                    ul[0] = lr[0];
                    lr[0] = tmp;
                }
                if (ul[1] > lr[1]) {
                    int tmp = ul[1];
                    ul[1] = lr[1];
                    lr[1] = tmp;
                }
                imageProps.put(ATTR_NORTH, new Double(ulEl.getLatitude().getValue()));
                imageProps.put(ATTR_WEST, new Double(ulEl.getLongitude().getValue()));
                imageProps.put(ATTR_SOUTH, new Double(lrEl.getLatitude().getValue()));
                imageProps.put(ATTR_EAST, new Double(lrEl.getLongitude().getValue()));
            } else if ((viewManager != null) && XmlUtil.hasAttribute(child, ATTR_NORTH)) {
                NavigatedDisplay display = (NavigatedDisplay) viewManager.getMaster();
                EarthLocation el1 = DisplayControlImpl.makeEarthLocation(toDouble(child, ATTR_NORTH),
                        toDouble(child, ATTR_WEST), 0);
                EarthLocation el2 = DisplayControlImpl.makeEarthLocation(toDouble(child, ATTR_SOUTH),
                        toDouble(child, ATTR_EAST), 0);
                ul = display.getScreenCoordinates(display.getSpatialCoordinates(el1, null));
                lr = display.getScreenCoordinates(display.getSpatialCoordinates(el2, null));
                imageProps.put(ATTR_NORTH, new Double(el1.getLatitude().getValue()));
                imageProps.put(ATTR_WEST, new Double(el1.getLongitude().getValue()));
                imageProps.put(ATTR_SOUTH, new Double(el2.getLatitude().getValue()));
                imageProps.put(ATTR_EAST, new Double(el2.getLongitude().getValue()));
            } else if (XmlUtil.hasAttribute(child, ATTR_LEFT)) {
                ul = new int[] { (int) toDouble(child, ATTR_LEFT, imageWidth),
                        (int) toDouble(child, ATTR_TOP, imageHeight) };
                lr = new int[] { (int) toDouble(child, ATTR_RIGHT, imageWidth),
                        (int) toDouble(child, ATTR_BOTTOM, imageHeight) };
            } else if (viewManager != null) {
                //TODO: Clip on visad coordinates
                NavigatedDisplay display = (NavigatedDisplay) viewManager.getMaster();
                ul = display.getScreenCoordinates(new double[] { -1, 1, 0 });
                lr = display.getScreenCoordinates(new double[] { 1, -1, 0 });
                int space = applyMacros(child, ATTR_SPACE, 0);
                int hspace = applyMacros(child, ATTR_HSPACE, space);
                int vspace = applyMacros(child, ATTR_VSPACE, space);
                ul[0] -= applyMacros(child, ATTR_SPACE_LEFT, hspace);
                ul[1] -= applyMacros(child, ATTR_SPACE_TOP, vspace);
                lr[0] += applyMacros(child, ATTR_SPACE_RIGHT, hspace);
                lr[1] += applyMacros(child, ATTR_SPACE_BOTTOM, vspace);
            } else {
                continue;
            }

            for (String attr : (List<String>) Misc.newList(ATTR_NORTH, ATTR_SOUTH, ATTR_EAST, ATTR_WEST)) {
                String kmlAttr = "kml." + attr;
                if (XmlUtil.hasAttribute(child, kmlAttr)) {
                    imageProps.put(attr, new Double(applyMacros(child, kmlAttr, 0.0)));
                }
            }

            ul[0] = Math.max(0, ul[0]);
            ul[1] = Math.max(0, ul[1]);

            lr[0] = Math.min(lr[0], imageWidth);
            lr[1] = Math.min(lr[1], imageHeight);

            newImage = ImageUtils.clip(image, ul, lr);
        } else if (tagName.equals(TAG_SPLIT)) {
            shouldIterateChildren = false;
            int width = image.getWidth(null);
            int height = image.getHeight(null);
            int cols = applyMacros(child, ATTR_COLUMNS, 2);
            int rows = applyMacros(child, ATTR_ROWS, 2);
            String file = applyMacros(child, ATTR_FILE);
            int cnt = 0;
            int hSpace = width / cols;
            int vSpace = height / rows;
            for (int row = 0; row < rows; row++) {
                for (int col = 0; col < cols; col++) {
                    pushProperties();
                    Hashtable myprops = new Hashtable();
                    putProperty("row", new Integer(row));
                    putProperty("column", new Integer(col));
                    putProperty("count", new Integer(++cnt));
                    String realFile = applyMacros(file, myprops);
                    Image splitImage = image.getSubimage(hSpace * col, vSpace * row, hSpace, vSpace);
                    processImage(ImageUtils.toBufferedImage(splitImage), realFile, child, myprops, viewManager,
                            new Hashtable());
                    popProperties();
                }
            }
        } else if (tagName.equals(TAG_THUMBNAIL)) {
            shouldIterateChildren = false;
            BufferedImage thumbImage = ImageUtils.toBufferedImage(resize(image, child));
            String thumbFile = applyMacros(child, ATTR_FILE, (String) null);
            if (thumbFile == null) {
                thumbFile = IOUtil.stripExtension(filename) + "_thumb" + IOUtil.getFileExtension(filename);
            }
            processImage(thumbImage, thumbFile, child, null, viewManager, new Hashtable());
        } else if (tagName.equals(TAG_KML)) {
            //NOOP
        } else if (tagName.equals(TAG_KMZFILE)) {
            //NOOP
        } else if (tagName.equals(TAG_OVERLAY)) {
            double transparency = applyMacros(child, ATTR_TRANSPARENCY, 0.0);
            Graphics2D g = image.createGraphics();
            String imagePath = applyMacros(child, ATTR_IMAGE, (String) null);

            float scale = (float) applyMacros(child, ATTR_SCALE, 1.0);

            Rectangle imageRect = new Rectangle(0, 0, imageWidth, imageHeight);
            Point pp = ImageUtils.parsePoint(applyMacros(child, ATTR_PLACE, "lr,-10,-10"), imageRect);
            String text = applyMacros(child, ATTR_TEXT, (String) null);
            Color bg = applyMacros(child, ATTR_BACKGROUND, (Color) null);
            if (text != null) {
                double angle = Math.toRadians(applyMacros(child, ATTR_ANGLE, 0.0));
                text = applyMacros(text);
                Color c = applyMacros(child, ATTR_COLOR, Color.white);
                if ((c != null) && (transparency > 0)) {
                    c = new Color(c.getRed(), c.getGreen(), c.getBlue(), ImageUtils.toAlpha(transparency));
                }
                //Color bg = applyMacros(child, ATTR_BACKGROUND,
                //                       (Color) null);
                if ((bg != null) && (transparency > 0)) {
                    bg = new Color(bg.getRed(), bg.getGreen(), bg.getBlue(), ImageUtils.toAlpha(transparency));
                }
                setFont(g, child);
                FontMetrics fm = g.getFontMetrics();
                Rectangle2D rect = fm.getStringBounds(text, g);
                int width = (int) rect.getWidth();
                int height = (int) (rect.getHeight());

                Point ap = ImageUtils.parsePoint(applyMacros(child, ATTR_ANCHOR, "lr,-10,-10"),
                        new Rectangle(0, 0, width, height));

                g.rotate(angle);

                if (bg != null) {
                    g.setColor(bg);
                    g.fillRect(pp.x - ap.x - 1, pp.y - ap.y - 1, (int) width + 2, (int) height + 2);
                }
                g.setColor(c);
                g.drawString(text, pp.x - ap.x, pp.y - ap.y + height);
            }

            if (imagePath != null) {
                Image overlay = ImageUtils.readImage(imagePath);
                if (overlay != null) {
                    if (transparency > 0) {
                        overlay = ImageUtils.setAlpha(overlay, transparency);
                    }

                    int width = overlay.getWidth(null);
                    int height = overlay.getHeight(null);
                    int scaledWidth = Math.round(width * scale);
                    int scaledHeight = Math.round(height * scale);

                    Image scaled = getScaledImage(overlay, scaledWidth, scaledHeight);
                    Rectangle overlayRect = new Rectangle(0, 0, scaledWidth, scaledHeight);
                    Point ap = ImageUtils.parsePoint(applyMacros(child, ATTR_ANCHOR, "lr,-10,-10"),
                            overlayRect);
                    g.drawImage(scaled, pp.x - ap.x, pp.y - ap.y, bg, null);
                }
            }
        } else {
            error("Unknown tag:" + tagName);
        }
        if (newImage != null) {
            String newFileName = applyMacros(child, ATTR_FILE, (String) null);
            if (shouldIterateChildren) {
                logger.trace("newFileName='{}' viewManager={} newImage={}", newFileName, viewManager, newImage);
                newImage = processImage(newImage, newFileName, child, null, viewManager, new Hashtable());
                logger.trace("finished processImage; result: {}", newImage);
            }
            if (newFileName != null) {
                logger.trace("calling writeImageToFile...");
                ImageUtils.writeImageToFile(newImage, getImageFileName(newFileName));
                logger.trace("finished writeImageToFile");
                debug("Writing image:" + newFileName);
            }
            if (!applyMacros(child, ATTR_COPY, false)) {
                image = newImage;
            }
        }
    }

    if (filename != null) {
        float quality = (float) applyMacros(node, ATTR_QUALITY, 1.0);
        List<String> fileToks = StringUtil.split(filename, ",", true, true);
        for (String file : fileToks) {
            file = getImageFileName(file);
            debug("Writing image:" + file);
            if (file.endsWith(FileManager.SUFFIX_KMZ) || file.endsWith(FileManager.SUFFIX_KML)) {
                GeoLocationInfo bounds = null;
                if (viewManager != null) {
                    bounds = viewManager.getVisibleGeoBounds();
                    ImageSequenceGrabber.subsetBounds(bounds, imageProps);
                    String tmpImageFile = getOutputPath(file);
                    ImageUtils.writeImageToFile(image, tmpImageFile, quality);
                    ImageWrapper imageWrapper = new ImageWrapper(tmpImageFile, null, bounds, null);
                    imageWrapper.setProperties(imageProps);
                    new ImageSequenceGrabber(file, getIdv(), this, node,
                            (List<ImageWrapper>) Misc.newList(imageWrapper), null, 1);
                }
            } else {
                logger.trace("another writeImageToFile call...");
                ImageUtils.writeImageToFile(image, file, quality);
                logger.trace("and it's done.");
            }
        }
    }
    logger.trace("result: {}", image);
    return image;
}