Java 2D - Frequently Asked Questions

Open all Close all

    Programming, Debugging and Performance questions

  • Q. Is there a list of the various runtime flags that Java2D uses?
  • Q. What kinds of graphics hardware acceleration does Java2D use?
    • What release you are running (we are constantly improving our hardware acceleration renderers, so each release has more to offer)
    • What OS you are running (our story on Windows is different from our story on Linux which is again different from our story on Solaris ... and the Apple folks have their own story for their platform)
    • What kind of hardware you have (your graphics card capabilities can be the single most important factor in enabling Java2D hardware acceleration).
  • Q. How can I get better performance for my Java2D application?
    • All of the articles listed for the "hardware acceleration" Q&A above
    • The gamers on http://javagaming.org are highly sensitive to performance and that web site has several good discussions about performance issues.
  • Q: Are there any tracing facilities in Java2D to help me track down performance issues in my application?

    -Dsun.java2d.trace=[log[,timestamp]],[count],[out:<filename>],[help],[verbose]

    System Properties for Java 2DTM Technology

    Image questions

  • Q: How do I create a resized copy of an image?
    
    
       BufferedImage createResizedCopy(Image originalImage, 
                                    int scaledWidth, int scaledHeight, 
                                    boolean preserveAlpha)
    {
        int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
        Graphics2D g = scaledBI.createGraphics();
        if (preserveAlpha) {
           g.setComposite(AlphaComposite.Src);
        }
        g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); 
        g.dispose();
        return scaledBI;
    }
    
    

    Class RenderingHints

    
    
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_[NEAREST_NEIGHBOR BILINEAR BICUBIC]); 
    
    
  • Q: Can I use Java2D to generate dynamic images from my servlet (or other server-side Java application)?
    
                   
    OutputStream
     
    import java.awt.*;
    import java.awt.image.*;
    import javax.imageio.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    
    public class ImageServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request,
                          HttpServletResponse response)
            throws ServletException, IOException
        {
            response.setContentType("image/jpeg");
    
            // Create image
            int width=200, height=200;
            BufferedImage image =
                new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    
            // Get drawing context
            Graphics2D g2d = image.createGraphics();
    
            // Fill background with white
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, width, height);
    
            // Draw a smiley face
            g2d.setColor(Color.YELLOW);
            g2d.fillOval(10, 10, 180, 180);
            g2d.setColor(Color.BLACK);
            g2d.fillOval(40, 40, 40, 40);
            g2d.fillOval(120, 40, 40, 40);
            g2d.fillRect(50, 150, 100, 10);
    
            // Dispose context
            g2d.dispose();
    
            // Write image to the output stream
            ServletOutputStream os = response.getOutputStream();        
    
            ImageIO.write(bi, "jpeg", os);
        }
    }
    
    
  • Q: I have an application that reads, writes, and processes images (but does not display them) using Java2D. When I run my application on Solaris or Linux, it complains that X11 is not available. What can I do to make my application work in this environment?

    BufferedImage

    -Djava.awt.headless=true

    http://www.realvnc.com

    http://www.x.org

    Font and Text questions

  • Q: What are the capabilities of the Java 2D text rendering system?
    • Antialiased and sub-pixel (aka LCD) text display
    • Transformed text
    • Text as shapes that can be filled with colours, gradient paints etc.
    • Rendering complex text scripts (eg Indic), Bidi text etc
    • APIs to locate and use platform fonts
    • APIs to directly load and register fonts from files and network resources.
  • Q: What are the different ways that text can be rendered using Java 2D?
    • java.awt.Graphics2D.drawString() draws a String of text using the current font and other rendering attributes. This is the most
    • java.awt.font.TextLayout object allows you to implement text editing yourself: it includes mixed styles, BIDI text layout, carets, highlighting, hit testing and many other features.
    • java.awt.font.GlyphVector can be used to accomplish GlyphVectorGlyphMetrics
    • Using Swing text components : since Swing is based upon Java 2D JTextField, JTextArea, and JEditorPane, which supports editing and multiple fonts and styles, all utilise the above Java 2D APIs. Many developers will therefore not directly use the 2D text APIs but will use the UI-oriented Swing interfaces.
  • Q. What font types does Java 2D support?

    TrueType

  • Q: Are any fonts bundled with Java 2D?

    TrueType

  • Q: How can I list all available fonts?

    java.awt.GraphicsEnvironment.getAvailableFontFamilyNames()java.awt.GraphicsEnvironment.getAllFonts()getAvailableFontFamilyNames()Font

  • Q: How can I make my custom font available to my Java application?
    • If you ship a private JRE with your application you can copy your fonts to $JAVAHOME/jre/lib/fonts since they will be available only to java applications executed by that JRE and will be visible via Java's font enumeration APIs.
    • You may also load custom fonts dynamically - by using java.awt.Font.createFont() to instantiate your fonts from files or network streams.
    • createFont()FontFont.deriveFont()Font.createFont()

      GraphicsEnvironment.registerFont()Font.createFont()

  • Q: Why does (eg) a 10 pt font in Java applications appear to have a different size from the same font at 10pt in a native application?
    • The DPI reported by platform APIs likely has no correspondence to the true DPI
    • Its unlikely that Java 2D's default matches the platform default.

    java.awt.Toolkit.getScreenResolution()

  • Q: How to I find if I use a font to display Cyrillic, or Hindi etc?

    Font.canDisplay()

  • Q. How can I specify the text antialiasing/font smoothing settings to be used by Swing in applications on Java SE 6?

    http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6274842

    java -Dawt.useSystemAAFontSettings=lcd

    • "false" corresponds to disabling font smoothing on the desktop.
    • "on" corresponds to Gnome Best shapes/Best contrast (no equivalent Windows desktop setting)
    • "gasp" corresponds to Windows "Standard" font smoothing [see note (*) below] (no equivalent Gnome desktop setting)
    • "lcd" corresponds to Gnome's "subpixel smoothing" and Windows "ClearType"

    TrueType

  • Q: How do I obtain font metrics?

    Fontmetricsjava.awt.Graphics.getFontMetrics(Font)FontRenderContext

    FontMetrics

  • Q. What is the difference between logical, visual and pixel bounds?

    Fontmetricsjava.awt.Graphics.getFontMetrics(Font)FontRenderContext

    Logical bounds are the most commonly used and include the ascent, descent, leading and advance of the text. They are useful to position the text correctly, particularly when appending one string after another or for multiple lines of text but they very likely will not enclose the rendered image. Particular examples of this may be glyphs which extend a pixel to the left of the "origin" at which it is drawn. "W" is a particular example - the leftmost long diagonal may extend to the left of the rendering origin. Glyphs in italic fonts are may commonly extend further to the right than the overall "advance" of the text may indicate. These two issues may lead to text being clipped on the left or the right if placed in a tight area measured using the advance of the string. Adding a couple of pixels of padding at each end is probably the simplest workaround for this. Similarly large descenders, or diacritics that are used in European languages may extend beyond the reported descent or ascent. If used to create a tight bounding box for a label for example this may clip at the bottom or top. Extra padding is again the simplest solution. To get the logical bounds of a String one may use any of following methods as appropriate :

    
    
    * Font.getStringBounds(...)
    * TextLayout.getAscent()
    * TextLayout.getDescent()
    * TextLayout.getLeading()
    * TextLayout.getAdvance()
    * GlyphVector.getLogicalBounds(...)
     
    
     
    
     
    
      * GlyphVector.getVisualBounds(...)
      * TextLayout.getBounds()
     
    
    TextLayout.getBounds()
     
    
    FontRenderContext
     
    
      * GlyphVector.getPixelBounds(...)
      * TextLayout.getPixelBounds(...) (new in Java SE 6)
     
    
    TextLayout.getPixelBounds(...)
    
    

    Printing questions

  • Q:What are the differences between the various printing APIs I see in the JDK?

    1.1 (aka AWT) printing - java.awt.PrintJob

    • A UI component-oriented printing API
    • Can print only the 1.1 "Graphics" API, not "Graphics2D" extensions
    • 2D printing - java.awt.print.PrinterJob

    • A more flexible API for printing documents
    • Can print all of Java 2D.
    • Callback printing model
    • Integrates with javax.print
    • Java Printing Service - javax.print packages

    • Adds discovery of printers and capabilities
    • Adds ability to specify job behaviour through attributes
    • Adds ability to install custom print services

    PrinterJob

  • Q Why is it so hard to print from Swing?
    • "how can I print all a JTable?"
    • "how can I just ask Swing to print the contents of a text component (rather than

    Class JTable

  • Q: What are the causes of large spool files from java.awt.print.PrinterJob and how can I avoid them?

    Printing using non opaque colours, gradient paints, and custom paints

    • the application printing code could avoid using these.
    • the application could render a selected area which uses these to an offscreen opaque BufferedImage and then draw that BufferedImage to the printer graphics.
    • the application could lower the device resolution of the print job which may be higher than needed, using the PrinterResolution attribute.

    Printing Text on Solaris with non-Postscript standard fonts

  • Q How do I keep the information from getting cut off from the top and left sides of the page when I print using the Java 2D printing API?
    
    
    PageFormat
        public int print(Graphics g, PageFormat pf, int pageIndex) 
            throws PrinterException
        {
            Graphics2D g2 = (Graphics2D)g;
            g2.translate(pf.getImageableX(), 
            pf.getImageableY() + 72);
            ...
        }
    
    
  • Q: How do I trouble shoot printing problems in Windows?
  • Q: How do I scale an image to fit a page?
    
    
    public int print(Graphics graphics, PageFormat pageFormat, int
     pageIndex) throws PrinterException
     {
     if(pageIndex > 0)
        return Printable.NO_SUCH_PAGE;
     Graphics2D g2d = (Graphics2D) graphics;
    
     //Set us to the upper left corner
     g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
     AffineTransform at = new AffineTransform();
     at.translate(0,0);
    
     //We need to scale the image properly so that it fits on one page.
     double xScale = pageFormat.getImageableWidth() / m_image.getWidth();
     double yScale = pageFormat.getImageableHeight() / m_image.getHeight();
     // Maintain the aspect ratio by taking the min of those 2 factors and
     using it to scale both dimensions.
     double aspectScale = Math.min(xScale, yScale);
    
     g2d.drawRenderedImage(m_image, at);
     return Printable.PAGE_EXISTS;
     }
     
     
  • Q: When I print using PDF or HTML using the corresponding DocFlavor, how come it is printed as garbage or plain text?

    PrintService

  • Q: Why is Java unable to print to my CUPS 1.2 printers ?
    
    
    Networking
    /Domain Sockets;/
    CUPS now supports the much faster UNIX  domain sockets for local printing
    
    
    • localhost:631 via a TCP/IP socket connection - this is the same as in
    • a unix domain socket at /var/run/cups/cups.sock

      http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6500903

    • Edit the cups configuration file, usually /etc/cups/cupsd.conf, and locate

      # Listen /var/run/cups/cups.sock

    • Ensure the line to listen on TCP/IP port 631 is present and UNcommented :
    • Finally save the file and restart cups
    
    
    sh /etc/init.d/cups restart
     
    cd /usr/lib
    ln -s libcups.so.2 libcups.so    
    
    

    Rendering questions

  • Q: What is the Rendering Process?
    • paint, which represents the color or pattern rendered to the destination for the text and shape draw and fill methods.
    • stroke, which describes the line style of the outline of shapes which are rendered using the shape draw (but not fill) methods.
    • font, which is the font of the text to be rendered in the text draw methods.
    • rendering hint, which suggests optional algorithms for how a primitive should be rendered, such as whether a faster or more accurate algorithm should be used.
    • transform, which represents the mapping from user space to device space and additional coordinate transforms, such as rotate and scale, to be applied to all primitives.
    • composite, which defines how the paint colors should replace or be mixed or blended with the colors already in the destination for all primitives.
    • clip, which identifies a subset of the pixels in the destination which are allowed to be changed. Pixels which fall outside the clip should never be modified by any primitive.
  • Q: What kinds of shapes can I draw using Java 2D?
    Arc2D Represents an arc defined by a bounding rectangle, start angle, angular extent, and a closure type.
    CubicCurve2D Represents a cubic parametric curve segment.
    Ellipse2D Represents an ellipse defined by a bounding rectangle.
    Line2D Represents a line segment in (x, y) coordinate space.
    Point2D A point representing a location in (x,y) coordinate space. Points render nothing when drawn or filled, but the Point2D class is used in many of the APIs that manipulate or construct shapes.
    QuadCurve2D Represents a quadratic parametric curve segment.
    Rectangle2D Represents a rectangle defined by a location (x, y) and dimension (w x h).
    RoundRectangle2D Represents a rectangle with rounded corners defined by a location (x, y), a dimension (w x h), and the width and height of the corner arcs.

    In addition to these classes that allow you to create common shapes, the Java 2D API provides two other classes that allow you to define odd shapes: GeneralPath and Area. Shapes created with GeneralPath must be created segment by segment, but this means that you can combine straight lines and curved lines into a single shape. The Area class supports constructive area geometry, which allows you to combine two shapes to create another shape, either by adding or intersecting the shapes, subtracting one shape from another, or by subtracting the intersection of the shapes.

    You can also create a Shape object from a String by calling getOutline on a TextLayout object. After creating the Shape, you can perform operations such as filling and transforming on the Shape.

    For more information on working with shapes in Java 2D, see the 2D Graphics tutorial.

  • Q: How do I draw on an image?
    
    
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(new File("images/bld.jpg"));
        } catch (IOException ioe) {
        }
        Graphics2D g2d = bi.createGraphics();
        g2d.drawLine(10, 10, 20, 20);  // draw a line on the image
        ...
        g2d.dispose();   
        
        
  • Q: I have a shape whose outline intersects itself. How do I control the filling of the shape?
  • Q: How do I draw a quadratic arrow-headed curves?
    
    
            ...
            GeneralPath path = new GeneralPath();
            float p1x = 10, p1y = 10;   // P1
            float p2x = 100, p2y = 10;  // P2
            float cx = 55, cy = 50;     // Control point of the curve
            float arrSize = 5;          // Size of the arrow segments
    
            float adjSize = (float)(arrSize/Math.sqrt(2));
            float ex = p2x - cx;
            float ey = p2y - cy;
            float abs_e = (float)Math.sqrt(ex*ex + ey*ey);
            ex /= abs_e;
            ey /= abs_e;
    
    
            // Creating quad arrow
            path.moveTo(p1x, p1y);
            path.quadTo(cx, cy, p2x, p2y);
            path.lineTo(p2x + (ey-ex)*adjSize, p2y - (ex + ey)*adjSize);
            path.moveTo(p2x, p2y);
            path.lineTo(p2x - (ey + ex)*adjSize, p2y + (ex - ey)*adjSize);
            ... 
            
            
  • Q: Why do I get unexpected results when I use the setTransform method of Graphics2D to perform transformations?

    To perform transformations, use these steps:

    Use getTransform to get the current transform:

    <blockquote>AffineTransform aT = g2.getTransform();

    Use the transform, translate, scale, shear, or rotate methods to concatenate a transform:

    <blockquote>g2.transform(...);

    Perform the rendering:

    <blockquote>g2.draw(...);

    Restore the original transform using setTransform:

    <blockquote>g2.setTransform(aT);