Example usage for java.awt AlphaComposite CLEAR

List of usage examples for java.awt AlphaComposite CLEAR

Introduction

In this page you can find the example usage for java.awt AlphaComposite CLEAR.

Prototype

int CLEAR

To view the source code for java.awt AlphaComposite CLEAR.

Click Source Link

Document

Both the color and the alpha of the destination are cleared (Porter-Duff Clear rule).

Usage

From source file:net.technicpack.ui.lang.ResourceLoader.java

public BufferedImage getCircleClippedImage(BufferedImage contentImage) {
    // copy the picture to an image with transparency capabilities
    BufferedImage outputImage = new BufferedImage(contentImage.getWidth(), contentImage.getHeight(),
            BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = (Graphics2D) outputImage.getGraphics();
    g2.drawImage(contentImage, 0, 0, null);

    // Create the area around the circle to cut out
    Area cutOutArea = new Area(new Rectangle(0, 0, outputImage.getWidth(), outputImage.getHeight()));

    int diameter = (outputImage.getWidth() < outputImage.getHeight()) ? outputImage.getWidth()
            : outputImage.getHeight();/*ww w . ja  v a2s. c om*/
    cutOutArea.subtract(new Area(new Ellipse2D.Float((outputImage.getWidth() - diameter) / 2,
            (outputImage.getHeight() - diameter) / 2, diameter, diameter)));

    // Set the fill color to an opaque color
    g2.setColor(Color.WHITE);
    // Set the composite to clear pixels
    g2.setComposite(AlphaComposite.Clear);
    // Turn on antialiasing
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    // Clear the cut out area
    g2.fill(cutOutArea);

    // dispose of the graphics object
    g2.dispose();

    return outputImage;
}

From source file:edu.ku.brc.ui.dnd.SimpleGlassPane.java

@Override
protected void paintComponent(Graphics graphics) {
    Graphics2D g = (Graphics2D) graphics;

    Rectangle rect = getInternalBounds();
    int width = rect.width;
    int height = rect.height;

    if (useBGImage) {
        // Create a translucent intermediate image in which we can perform
        // the soft clipping
        GraphicsConfiguration gc = g.getDeviceConfiguration();
        if (img == null || img.getWidth() != width || img.getHeight() != height) {
            img = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        }/*w  ww .  j  av a  2 s .c  o  m*/
        Graphics2D g2 = img.createGraphics();

        // Clear the image so all pixels have zero alpha
        g2.setComposite(AlphaComposite.Clear);
        g2.fillRect(0, 0, width, height);

        g2.setComposite(AlphaComposite.Src);
        g2.setColor(new Color(0, 0, 0, 85));
        g2.fillRect(0, 0, width, height);

        if (delegateRenderer != null) {
            delegateRenderer.render(g, g2, img);
        }

        g2.dispose();

        // Copy our intermediate image to the screen
        g.drawImage(img, rect.x, rect.y, null);
    }

    super.paintComponent(graphics);

    if (StringUtils.isNotEmpty(text)) {
        Graphics2D g2 = (Graphics2D) graphics;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(fillColor);
        g2.fillRect(margin.left, margin.top, rect.width, rect.height);

        g2.setFont(new Font((new JLabel()).getFont().getName(), Font.BOLD, pointSize));
        FontMetrics fm = g2.getFontMetrics();

        int tw = fm.stringWidth(text);
        int th = fm.getHeight();
        int tx = (rect.width - tw) / 2;
        int ty = (rect.height - th) / 2;

        if (yPos != null) {
            ty = yPos;
        }

        int expand = 20;
        int arc = expand * 2;

        g2.setColor(new Color(0, 0, 0, 50));

        int x = margin.left + tx - (expand / 2);
        int y = margin.top + ty - fm.getAscent() - (expand / 2);

        drawBGContainer(g2, true, x + 4, y + 6, tw + expand, th + expand, arc, arc);

        g2.setColor(new Color(255, 255, 255, 220));
        drawBGContainer(g2, true, x, y, tw + expand, th + expand, arc, arc);

        g2.setColor(Color.DARK_GRAY);
        drawBGContainer(g2, false, x, y, tw + expand, th + expand, arc, arc);

        g2.setColor(textColor == null ? Color.BLACK : textColor);
        g2.drawString(text, tx, ty);
    }
}

From source file:org.jas.gui.ImagePanel.java

@Override
protected void paintComponent(Graphics g) {
    if (portrait == null) {
        super.paintComponent(g);
        return;//from   ww w . j av a2 s  . c  o m
    }
    try {
        // Create a translucent intermediate image in which we can perform the soft clipping
        GraphicsConfiguration gc = ((Graphics2D) g).getDeviceConfiguration();
        BufferedImage intermediateBufferedImage = gc.createCompatibleImage(getWidth(), getHeight(),
                Transparency.TRANSLUCENT);
        Graphics2D bufferGraphics = intermediateBufferedImage.createGraphics();

        // Clear the image so all pixels have zero alpha
        bufferGraphics.setComposite(AlphaComposite.Clear);
        bufferGraphics.fillRect(0, 0, getWidth(), getHeight());

        // Render our clip shape into the image. Shape on where to paint
        bufferGraphics.setComposite(AlphaComposite.Src);
        bufferGraphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        bufferGraphics.setColor(Color.WHITE);
        bufferGraphics.fillRoundRect(0, 0, getWidth(), getHeight(), (int) (getWidth() * arcWidth),
                (int) (getHeight() * arcHeight));

        // SrcAtop uses the alpha value as a coverage value for each pixel stored in the
        // destination shape. For the areas outside our clip shape, the destination
        // alpha will be zero, so nothing is rendered in those areas. For
        // the areas inside our clip shape, the destination alpha will be fully
        // opaque.
        bufferGraphics.setComposite(AlphaComposite.SrcAtop);
        bufferGraphics.drawImage(portrait, 0, 0, getWidth(), getHeight(), null);
        bufferGraphics.dispose();

        // Copy our intermediate image to the screen
        g.drawImage(intermediateBufferedImage, 0, 0, null);

    } catch (Exception e) {
        log.warn("Error: Creating Renderings", e);
    }
}

From source file:com.codename1.android.AndroidLayoutImporter.java

Border createImageBorder(String imageName) {
    Image im = outputResources.getImage(imageName);
    if (im == null) {
        return null;
    }//  w  w  w .  j av  a  2 s  .  c o m
    EncodedImage eim = null;
    if (im instanceof EncodedImage) {
        eim = (EncodedImage) im;
    } else {
        eim = EncodedImage.createFromImage(im, imageName.endsWith(".jpg"));
    }

    BufferedImage center = new BufferedImage(1, im.getHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = (Graphics2D) center.createGraphics();
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
    g2.fillRect(0, 0, im.getWidth(), im.getHeight());
    g2.dispose();

    EncodedImage placeholder = EncodedImage.create(toPng(center));

    outputResources.setImage("TransparentPlaceholer" + center.getWidth() + "x" + center.getHeight() + ".png",
            placeholder);

    return Border.createHorizonalImageBorder(eim, placeholder, placeholder);
}

From source file:org.openmeetings.app.data.record.BatikMethods.java

public void drawArrow(SVGGraphics2D g2d, GeomPoint start, GeomPoint end, float thickness, float alpha,
        Color linecoler, Color fillColor) {

    if (start.equals(end))
        return;/*  ww  w .  j av  a2s  .com*/

    //      (double edgeControlPosition, double edgeControlSize,
    //            double headLength, double headWidth, double shaftControlPosition,
    //            double shaftControlSize, float shaftPosition, double shaftThickness)
    ArrowStyle arrowStyle = new ArrowStyle(0.5, 0.5, thickness * 5, thickness * 5, 0.5, 0.5, 0, thickness);

    GeomPoint fullVect = end.subtract(start);
    double halfWidth = (arrowStyle.headWidth != -1) ? arrowStyle.headWidth / 2 : arrowStyle.headLength / 2;

    //Figure out the line start/end points
    GeomPoint startNorm = new GeomPoint();
    startNorm.setLocation(fullVect.getY(), -fullVect.getX());
    startNorm.normalize(arrowStyle.shaftThickness / 2);
    GeomPoint start1 = start.add(startNorm);
    GeomPoint start2 = start.subtract(startNorm);
    GeomPoint end1 = end.add(startNorm);
    GeomPoint end2 = end.subtract(startNorm);

    //log.debug("startNorm: "+startNorm.toString());
    //log.debug("start1: "+start1.toString());
    //log.debug("start2: "+start2.toString());
    //log.debug("end1: "+end1.toString());
    //log.debug("end2: "+end2.toString());

    //figure out where the arrow head starts
    GeomPoint headPnt = fullVect.clone();
    //log.debug("headPnt 1: "+headPnt.toString());
    //log.debug("headPnt.length 1: "+headPnt.length());
    //log.debug("arrowStyle.headLength 1: "+arrowStyle.headLength);
    headPnt.normalize(headPnt.length() - arrowStyle.headLength);
    //log.debug("headPnt 2: "+headPnt.toString());
    headPnt = headPnt.add(start);
    //log.debug("headPnt 3: "+headPnt.toString());

    //calculate the arrowhead corners
    GeomPoint headPntNorm = startNorm.clone();
    //log.debug("headPntNorm ^^: "+headPntNorm.toString());
    //log.debug("halfWidth ^^: "+halfWidth);
    headPntNorm.normalize(halfWidth);
    //log.debug("headPntNorm: "+headPntNorm.toString());
    GeomPoint edge1 = headPnt.add(headPntNorm);
    GeomPoint edge2 = headPnt.subtract(headPntNorm);

    //log.debug("edge1: "+edge1.toString());
    //log.debug("edge2: "+edge2.toString());

    //Figure out where the arrow connects the the shaft, then calc the intersections
    GeomPoint shaftCenter = GeomPoint.interpolate(end, headPnt, arrowStyle.shaftPosition);
    //log.debug("end"+end.toString());
    //log.debug("headPnt: "+headPnt.toString());
    //log.debug("arrowStyle.shaftPosition: "+arrowStyle.shaftPosition);
    //log.debug("shaftCenter: "+shaftCenter);
    //log.debug("edge1: "+edge1);
    //shaftCenter.setLocation(185.857864376269, 185.857864376269);
    GeomPoint inter1 = GeomPoint.getLineIntersection(start1, end1, shaftCenter, edge1);
    GeomPoint inter2 = GeomPoint.getLineIntersection(start2, end2, shaftCenter, edge2);

    //log.debug("inter1: "+inter1.toString());
    //log.debug("inter2: "+inter2.toString());

    //Figure out the control points
    GeomPoint edgeCenter = GeomPoint.interpolate(end, headPnt, (float) arrowStyle.edgeControlPosition);
    GeomPoint edgeNorm = startNorm.clone();
    edgeNorm.normalize(halfWidth * arrowStyle.edgeControlSize);
    //log.debug("halfWidth*arrowStyle.edgeControlSize: "+(halfWidth*arrowStyle.edgeControlSize));
    //log.debug("edgeNorm: "+edgeNorm.toString());
    GeomPoint edgeCntrl1 = edgeCenter.add(edgeNorm);
    GeomPoint edgeCntrl2 = edgeCenter.subtract(edgeNorm);

    //log.debug("edgeCntrl1: "+edgeCntrl1.toString());
    //log.debug("edgeCntrl2: "+edgeCntrl2.toString());

    g2d.setPaint(new Color(255, 0, 0));

    //      graphics.moveTo(start1.x,start1.y);
    //      graphics.lineTo(inter1.x,inter1.y);
    //      graphics.lineTo(edge1.x,edge1.y);
    //      graphics.curveTo(edgeCntrl1.x,edgeCntrl1.y,end.x,end.y);
    //      graphics.curveTo(edgeCntrl2.x,edgeCntrl2.y,edge2.x,edge2.y);
    //      graphics.lineTo(inter2.x,inter2.y);
    //      graphics.lineTo(start2.x,start2.y);
    //      graphics.lineTo(start1.x,start1.y);

    //      log.debug("moveTo"+start1.x+","+start1.y);
    //      log.debug("lineTo"+inter1.x+","+inter1.y);
    //      log.debug("lineTo"+edge1.x+","+edge1.y);
    //      log.debug("quadTo"+edgeCntrl1.x+","+edgeCntrl1.y+","+end.x+","+end.y);
    //      log.debug("quadTo"+edgeCntrl2.x+","+edgeCntrl2.y+","+edge2.x+","+edge2.y);
    //      log.debug("lineTo"+inter2.x+","+inter2.y);
    //      log.debug("lineTo"+start2.x+","+start2.y);
    //      log.debug("lineTo"+start1.x+","+start1.y);

    GeneralPath graphics = new GeneralPath();
    graphics.moveTo(start1.x, start1.y);
    graphics.lineTo(inter1.x, inter1.y);
    graphics.lineTo(edge1.x, edge1.y);
    graphics.quadTo(edgeCntrl1.x, edgeCntrl1.y, end.x, end.y);
    graphics.quadTo(edgeCntrl2.x, edgeCntrl2.y, edge2.x, edge2.y);
    graphics.lineTo(inter2.x, inter2.y);
    graphics.lineTo(start2.x, start2.y);
    graphics.lineTo(start1.x, start1.y);
    graphics.closePath();

    int[] rules = new int[8];

    //all possible Compositing Rules:
    rules[0] = AlphaComposite.SRC_OVER;
    rules[1] = AlphaComposite.DST_OVER;
    rules[2] = AlphaComposite.CLEAR;
    rules[3] = AlphaComposite.SRC;
    rules[4] = AlphaComposite.SRC_IN;
    rules[5] = AlphaComposite.DST_IN;
    rules[6] = AlphaComposite.SRC_OUT;
    rules[7] = AlphaComposite.DST_OUT;

    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, alpha));
    g2d.setStroke(new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));

    if (linecoler != null) {
        g2d.setPaint(linecoler);
        g2d.draw(graphics);
    }

    if (fillColor != null) {
        g2d.setPaint(fillColor);
        g2d.fill(graphics);
    }

}

From source file:de.tor.tribes.ui.panels.MinimapPanel.java

private boolean redraw() {
    Village[][] mVisibleVillages = DataHolder.getSingleton().getVillages();

    if (mVisibleVillages == null || mBuffer == null) {
        return false;
    }/*from  w w w.  j  av a 2s.  c o m*/

    Graphics2D g2d = (Graphics2D) mBuffer.getGraphics();
    Composite tempC = g2d.getComposite();
    //clear
    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
    g2d.fillRect(0, 0, mBuffer.getWidth(), mBuffer.getHeight());

    //reset composite
    g2d.setComposite(tempC);

    boolean markPlayer = GlobalOptions.getProperties().getBoolean("mark.villages.on.minimap");
    if (ServerSettings.getSingleton().getMapDimension() == null) {
        //could not draw minimap if dimensions are not loaded yet
        return false;
    }
    boolean showBarbarian = GlobalOptions.getProperties().getBoolean("show.barbarian");

    Color DEFAULT = Constants.DS_DEFAULT_MARKER;
    try {
        int mark = Integer.parseInt(GlobalOptions.getProperty("default.mark"));
        if (mark == 0) {
            DEFAULT = Constants.DS_DEFAULT_MARKER;
        } else if (mark == 1) {
            DEFAULT = Color.RED;
        } else if (mark == 2) {
            DEFAULT = Color.WHITE;
        }
    } catch (Exception e) {
        DEFAULT = Constants.DS_DEFAULT_MARKER;
    }

    Rectangle mapDim = ServerSettings.getSingleton().getMapDimension();
    double wField = mapDim.getWidth() / (double) visiblePart.width;
    double hField = mapDim.getHeight() / (double) visiblePart.height;

    UserProfile profile = GlobalOptions.getSelectedProfile();
    Tribe currentTribe = InvalidTribe.getSingleton();
    if (profile != null) {
        currentTribe = profile.getTribe();
    }

    for (int i = visiblePart.x; i < (visiblePart.width + visiblePart.x); i++) {
        for (int j = visiblePart.y; j < (visiblePart.height + visiblePart.y); j++) {
            Village v = mVisibleVillages[i][j];
            if (v != null) {
                Color markerColor = null;
                boolean isLeft = false;
                if (v.getTribe() == Barbarians.getSingleton()) {
                    isLeft = true;
                } else {
                    if ((currentTribe != null) && (v.getTribe().getId() == currentTribe.getId())) {
                        //village is owned by current player. mark it dependent on settings
                        if (markPlayer) {
                            markerColor = Color.YELLOW;
                        }
                    } else {
                        try {
                            Marker marker = MarkerManager.getSingleton().getMarker(v.getTribe());
                            if (marker != null && !marker.isShownOnMap()) {
                                marker = null;
                                markerColor = DEFAULT;
                            }

                            if (marker == null) {
                                marker = MarkerManager.getSingleton().getMarker(v.getTribe().getAlly());
                                if (marker != null && marker.isShownOnMap()) {
                                    markerColor = marker.getMarkerColor();
                                }
                            } else {
                                if (marker.isShownOnMap()) {
                                    markerColor = marker.getMarkerColor();
                                }
                            }
                        } catch (Exception e) {
                            markerColor = null;
                        }
                    }
                }

                if (!isLeft) {
                    if (markerColor != null) {
                        g2d.setColor(markerColor);
                    } else {
                        g2d.setColor(DEFAULT);
                    }
                    g2d.fillRect((int) Math.round((i - visiblePart.x) * wField),
                            (int) Math.round((j - visiblePart.y) * hField), (int) Math.floor(wField),
                            (int) Math.floor(hField));
                } else {
                    if (showBarbarian) {
                        g2d.setColor(Color.LIGHT_GRAY);
                        g2d.fillRect((int) Math.round((i - visiblePart.x) * wField),
                                (int) Math.round((j - visiblePart.y) * hField), (int) Math.floor(wField),
                                (int) Math.floor(hField));
                    }
                }
            }
        }
    }

    try {
        if (GlobalOptions.getProperties().getBoolean("map.showcontinents")) {
            g2d.setColor(Color.BLACK);
            Composite c = g2d.getComposite();
            Composite a = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f);
            Font f = g2d.getFont();
            Font t = new Font("Serif", Font.BOLD, (int) Math.round(30 * hField));
            g2d.setFont(t);
            int fact = 10;
            int mid = (int) Math.round(50 * wField);

            for (int i = 0; i < 10; i++) {
                for (int j = 0; j < 10; j++) {
                    g2d.setComposite(a);

                    String conti = "K" + (j * 10 + i);
                    Rectangle2D bounds = g2d.getFontMetrics(t).getStringBounds(conti, g2d);
                    int cx = i * fact * 10 - visiblePart.x;
                    int cy = j * fact * 10 - visiblePart.y;
                    cx = (int) Math.round(cx * wField);
                    cy = (int) Math.round(cy * hField);
                    g2d.drawString(conti, (int) Math.rint(cx + mid - bounds.getWidth() / 2),
                            (int) Math.rint(cy + mid + bounds.getHeight() / 2));
                    g2d.setComposite(c);
                    int wk = 100;
                    int hk = 100;

                    if (i == 9) {
                        wk -= 1;
                    }
                    if (j == 9) {
                        hk -= 1;
                    }

                    g2d.drawRect(cx, cy, (int) Math.round(wk * wField), (int) Math.round(hk * hField));
                }
            }
            g2d.setFont(f);
        }
    } catch (Exception e) {
        logger.error("Creation of Minimap failed", e);
    }
    g2d.dispose();
    return true;
}

From source file:pl.edu.icm.visnow.system.main.VisNow.java

private static void renderSplashFrame(float progress, String loadText, String bottomTextUpperLine,
        String bottomTextLowerLine) {
    if (splash == null) {
        return;/*from  w  ww. j  av  a2  s  .  c om*/
    }

    try {
        Graphics2D g = splash.createGraphics();
        if (g == null) {
            return;
        }

        if (!splash.isVisible())
            return;

        Rectangle bounds = splash.getBounds();
        Font f = g.getFont();
        FontMetrics fm = g.getFontMetrics(f);
        java.awt.geom.Rectangle2D rect = fm.getStringBounds(loadText, g);
        int texth = (int) Math.ceil(rect.getHeight());
        g.setComposite(AlphaComposite.Clear);
        //g.setColor(Color.RED);
        g.fillRect(PROGRESS_TEXT_X_POSITION, bounds.height - PROGRESS_TEXT_Y_MARGIN - texth - 5,
                bounds.width - PROGRESS_TEXT_X_POSITION, texth + 10);

        g.setFont(lowerLineFont);
        fm = g.getFontMetrics(g.getFont());
        rect = fm.getStringBounds(bottomTextLowerLine, g);
        int lowerLineTextHeight = (int) Math.ceil(rect.getHeight());
        g.fillRect(BOTTOM_TEXT_X_MARGIN, bounds.height - BOTTOM_TEXT_Y_MARGIN - lowerLineTextHeight - 5,
                bounds.width - BOTTOM_TEXT_X_MARGIN, lowerLineTextHeight + 10);

        g.setFont(f);
        fm = g.getFontMetrics(g.getFont());
        rect = fm.getStringBounds(bottomTextUpperLine, g);
        texth = (int) Math.ceil(rect.getHeight());
        g.fillRect(BOTTOM_TEXT_X_MARGIN, bounds.height - lowerLineTextHeight - BOTTOM_TEXT_Y_MARGIN - texth - 5,
                bounds.width - BOTTOM_TEXT_X_MARGIN, lowerLineTextHeight + 10);

        g.setPaintMode();
        //        g.setColor(Color.BLACK);
        g.setColor(new Color(0, 75, 50));
        g.drawString(loadText, PROGRESS_TEXT_X_POSITION, bounds.height - PROGRESS_TEXT_Y_MARGIN);
        g.drawString(bottomTextUpperLine, BOTTOM_TEXT_X_MARGIN,
                bounds.height - lowerLineTextHeight - BOTTOM_TEXT_Y_MARGIN);
        g.setFont(lowerLineFont);
        g.drawString(bottomTextLowerLine, BOTTOM_TEXT_X_MARGIN, bounds.height - BOTTOM_TEXT_Y_MARGIN);
        g.setFont(f);

        //        g.setColor(Color.BLACK);
        g.setColor(new Color(0, 150, 100));
        g.drawRect(PROGRESS_BAR_X_MARGIN, bounds.height - PROGRESS_BAR_Y_MARGIN,
                bounds.width - PROGRESS_BAR_X_MARGIN, PROGRESS_BAR_HEIGHT);
        int progressWidth = bounds.width - 2 * PROGRESS_BAR_X_MARGIN;
        int done = (int) (progressWidth * progress);
        g.fillRect(PROGRESS_BAR_X_MARGIN, bounds.height - PROGRESS_BAR_Y_MARGIN, PROGRESS_BAR_X_MARGIN + done,
                PROGRESS_BAR_HEIGHT);
        if (progress >= 1.0f) {
            g.fillRect(PROGRESS_BAR_X_MARGIN, bounds.height - PROGRESS_BAR_Y_MARGIN,
                    bounds.width - PROGRESS_BAR_X_MARGIN, PROGRESS_BAR_HEIGHT);
        }

        splash.update();
    } catch (IllegalStateException ex) {
    }
}

From source file:tufts.vue.LWComponent.java

/**
 * Useful for drawing drag images into an existing graphics buffer, or drawing exportable images.
 *
 * @param alpha 0.0 (invisible) to 1.0 (no alpha -- completely opaque)
 * @param maxSize max dimensions for image. May be null.  Image may be smaller than maxSize.
 * @param fillColor -- if non-null, will be rendered as background for image.
 * @param zoomRequest -- desired zoom; ignored if maxSize is non-null
 * also set, background fill will have transparency of alpha^3 to enhance contrast.
 *//*  www .  j a va 2 s  .  c  om*/

public void drawImage(Graphics2D g, double alpha, Dimension maxSize, Color fillColor, double zoomRequest) {
    //if (DEBUG.IMAGE) out("drawImage; size " + maxSize);

    final boolean drawBorder = false;// this instanceof LWMap; // hack for dragged images of LWMaps

    final Rectangle2D.Float bounds = getImageBounds();
    final Rectangle clip = g.getClipBounds();
    final Size fillSize = new Size(bounds);
    final double zoom = computeZoomAndSize(bounds, maxSize, zoomRequest, fillSize);

    if (DEBUG.IMAGE)
        out(TERM_GREEN + "drawImage:" + "\n\t   mapBounds: " + fmt(bounds) + "\n\t        fill: " + fillColor
                + "\n\t     maxSize: " + maxSize + "\n\t zoomRequest: " + zoomRequest + "\n\t     fitZoom: "
                + zoom + "\n\t    fillSize: " + fillSize + "\n\t          gc: " + g + "\n\t        clip: "
                + fmt(clip) + "\n\t       alpha: " + alpha + TERM_CLEAR);

    final int width = fillSize.pixelWidth();
    final int height = fillSize.pixelHeight();

    final DrawContext dc = new DrawContext(g, this);

    dc.setInteractive(false);

    if (alpha == OPAQUE) {
        dc.setPrintQuality();
    } else {
        // if alpha, assume drag image (todo: better specified as an argument)
        dc.setDraftQuality();
    }

    dc.setBackgroundFill(getRenderFillColor(null)); // sure we want null here?
    dc.setClipOptimized(false); // always draw all children -- don't bother to check bounds
    if (DEBUG.IMAGE)
        out(TERM_GREEN + "drawImage: " + dc + TERM_CLEAR);

    if (fillColor != null) {
        //             if (false && alpha != OPAQUE) {
        //                 Color c = fillColor;
        //                 // if we have an alpha and a fill, amplify the alpha on the background fill
        //                 // by changing the fill to one that has alpha*alpha, for a total of
        //                 // alpha*alpha*alpha given our GC already has an alpha set.
        //                 fillColor = new Color(c.getRed(), c.getGreen(), c.getBlue(), (int) (alpha*alpha*255+0.5));
        //             }
        if (alpha != OPAQUE)
            dc.setAlpha(alpha, AlphaComposite.SRC); // erase any underlying in cache
        if (DEBUG.IMAGE)
            out("drawImage: fill=" + fillColor);
        g.setColor(fillColor);
        g.fillRect(0, 0, width, height);
    } else { //if (alpha != OPAQUE) {
        // we didn't have a fill, but we have an alpha: make sure any cached data is cleared
        // todo?: if fill is null, we need to clear as well -- it means we have implied alpha on any non-drawn bits
        // TODO: if this is a selection drag, we usually want to fill with the map color (or ideally, the color
        // of the common parent, e.g., a slide, if there's one common parent)
        dc.g.setComposite(AlphaComposite.Clear);
        g.fillRect(0, 0, width, height);
    }

    //if (alpha != OPAQUE)
    dc.setAlpha(alpha, AlphaComposite.SRC);

    if (DEBUG.IMAGE && DEBUG.META) {
        // Fill the entire imageable area
        g.setColor(Color.green);
        g.fillRect(0, 0, Short.MAX_VALUE, Short.MAX_VALUE);
    }

    final AffineTransform rawTransform = g.getTransform();

    if (zoom != 1.0)
        dc.g.scale(zoom, zoom);

    // translate so that the upper left corner of the map region
    // we're drawing is at 0,0 on the underlying image

    g.translate(-bounds.getX(), -bounds.getY());

    // GC *must* have a bounds set or we get NPE's in JComponent (textBox) rendering
    dc.setMasterClip(bounds);

    if (DEBUG.IMAGE && DEBUG.META) {
        // fill the clipped area so we can check our clip bounds
        dc.g.setColor(Color.red);
        dc.g.fillRect(-Short.MAX_VALUE / 2, -Short.MAX_VALUE / 2, // larger values than this can blow out internal GC code and we get nothing
                Short.MAX_VALUE, Short.MAX_VALUE);
    }

    if (this instanceof LWImage) {
        // for some reason, raw images don't seem to want to draw unless we fill first
        dc.g.setColor(Color.white);
        dc.g.fill(bounds);
    }

    // render to the image through the DrawContext/GC pointing to it
    draw(dc);

    if (drawBorder) {
        g.setTransform(rawTransform);
        //g.setColor(Color.red);
        //g.fillRect(0,0, Short.MAX_VALUE, Short.MAX_VALUE);
        if (DEBUG.IMAGE) {
            g.setColor(Color.black);
            dc.setAntiAlias(false);
        } else
            g.setColor(Color.darkGray);
        g.drawRect(0, 0, width - 1, height - 1);
    }

    if (DEBUG.IMAGE)
        out(TERM_GREEN + "drawImage: completed\n" + TERM_CLEAR);

}