Professional Documents
Culture Documents
Graphics Programming With Java 2D
Graphics Programming With Java 2D
Java 2D API
Shapes, text, and images
A uniform mechanism for performing
transformations
rotation and scaling, on objects.
A wide array of presentation devices such as
displays and printers,
image formats and encodings,
color spaces,
rendering techniques and effects.
Comprehensive text and font handling,
color support
Rendering
The process of taking a collection of shapes,
text, and images &
Figure out what colors the pixels should be
on a screen or printer.
In the Java 2D API, the Graphics2D class is
the rendering engine:
the Graphics2D object contains state attributes, such
as color &
applies these attributes to the primitives when
rendering them to various output devices.
The attributes of Graphics2D object
Paint: represents the color or pattern that the primitive will
be when it is rendered.
Stroke: describes the line style of the outline of the shape
Font: the font of the text to be rendered
Rendering hint: suggests how a primitive should be
rendered, such as whether a faster or more accurate
algorithm should be used.
Transform: represents the mapping from user space to
device space and additional graphic transforms, such as
rotate and scale, to be applied to particular primitives.
Composite: defines how the overlapping parts of two
graphic objects should be rendered
Clip: identifies the part of a primitive that is to be rendered
The Rendering Process
What is a rasterizer?
Takes ideal shapes and produces
coverage values for each pixel.
The coverage values represent how much
of each pixel is covered by the shape.
These coverage values are called alpha
values.
Each pixel has its own alpha value which
indicates the transparency of the pixel
Is it possible to use native
rasterizer?
Java 2D does not use a native rasterizer for
rendering fonts
Uses the T2K font rasterizer from Type Solutions
http://www.typesolutions.com/
Subtraction
Intersection
Exclusive-or (XOR)
package untitled71;
import javax.swing.UIManager;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import javax.swing.*;
// This applet renders a pear, using CAG methods: add, intersect, and subtract.
public class Pear extends JApplet {
Ellipse2D.Double circle, oval, leaf, stem;
Area circ, ov, leaf1, leaf2, st1, st2;
public void init() {
circle = new Ellipse2D.Double();
oval = new Ellipse2D.Double();
leaf = new Ellipse2D.Double();
stem = new Ellipse2D.Double();
circ = new Area(circle);
ov = new Area(oval);
leaf1 = new Area(leaf);
leaf2 = new Area (leaf);
st1 = new Area (stem);
st2 = new Area (stem);
setBackground (Color.white); }
public void paint (Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Dimension d = getSize()
int w = d.width;
int h = d.height;
double ew = w/2;
double eh = h/2;
g2.setColor(Color.green);
// Creates the first leaf by filling the intersection of two Area objects created from an
ellipse.
leaf.setFrame(ew-16, eh-29, 15.0, 15.0);
leaf1 = new Area (leaf);
leaf.setFrame(ew-14, eh-47, 30.0, 30.0);
leaf2 = new Area (leaf);
leaf1.intersect (leaf2);
g2.fill(leaf1);
// Creates the second leaf.
leaf.setFrame (ew+1, eh-29, 15.0, 15.0);
leaf1 = new Area (leaf);
leaf2.intersect (leaf1);
g2.fill(leaf2);
g2.setColor(Color.black);
/** Creates the stem by filling the Area resulting from the subtraction of two
Area objects created from an ellipse.**/
g2.setColor(Color.yellow);
/ ** Creates the pear itself by filling the Area resulting from the union of two
Area objects created by two different ellipses **/
}
java.awt.font.* Class Diagrams
Font
http://www.falkhausen.de/en/diagram/html/java.awt.font.Font.html
Interfaces: MultipleMaster, OpenType
Classes: java.awt.Font, FontRenderContext, LineMetrics, java.awt.FontMetrics
TextLayout
http://www.falkhausen.de/en/diagram/html/java.awt.font.TextLayout.html
Classes: TextHitInfo, TextLayout, TextLayout.CaretPolicy, LineBreakMeasurer,
TextMeasurer
Attribute
http://www.falkhausen.de/en/diagram/html/java.awt.font.Attribute.html
Classes: java.text.AttributedCharacterIterator.Attribute, GraphicAttribute,
ImageGraphicAttribute, TextAttribute, ShapeGraphicAttribute,
NumericShaper, TransformAttribute
Glyph
http://www.falkhausen.de/en/diagram/html/java.awt.font.Glyph.html
Classes: GlyphMetrics, GlyphVector, GlyphJustificationInfo
java.awt.geom.* Class Diagrams
Shapes
http://www.falkhausen.de/en/diagram/html/java.awt.geom.Shape.html
Interfaces: java.awt.Shape
Lines
http://www.falkhausen.de/en/diagram/html/java.awt.geom.LineShapes.html
Interfaces: java.awt.Shape
Classes: QuadCurve2D, QuadCurve2D.Double, QuadCurve2D.Float,
CubicCurve2D, Line2D, CubicCurve2D.Double, Line2D.Double,
CubicCurve2D.Float, Line2D.Float
Rects
http://www.falkhausen.de/en/diagram/html/java.awt.geom.RectangleShapes.html
Interfaces: java.awt.Shape
Classes: RectangularShape, RoundRectangle2D.Float, RoundRectangle2D,
RoundRectangle2D.Double,
Ellipse2D.Double, Rectangle2D, Ellipse2D, Ellipse2D.Float,
Arc2D, Arc2D.Float,
java.awt.Rectangle, Rectangle2D.Float, Rectangle2D.Double, Arc2D.Double
java.awt.geom.* Class Diagrams
cont’d
Asym
http://www.falkhausen.de/en/diagram/html/java.awt.geom.MiscShape.html
Interfaces: java.awt.Shape
Classes: GeneralPath, Area, java.awt.Polygon
Point
http://www.falkhausen.de/en/diagram/html/java.awt.geom.Point.html
Classes: Point2D, Dimension2D, java.awt.Insets, java.awt.Dimension,
java.awt.Point, Point2D.Float, Point2D.Double
Misc
http://www.falkhausen.de/en/diagram/html/java.awt.geom.Misc.html
Interfaces: PathIterator
Classes: AffineTransform, FlatteningPathIterator
java.awt.event.* Class Diagrams
Listener
http://www.falkhausen.de/en/diagram/html/java.awt.event.Listener.html
Interfaces: java.util.EventListener, AWTEventListener, ActionListener,
KeyListener, AdjustmentListener, ComponentListener,
MouseWheelListener, ContainerListener, MouseListener, FocusListener,
MouseMotionListener, HierarchyBoundsListener, WindowStateListener,
HierarchyListener, WindowFocusListener, InputMethodListener,
WindowListener, ItemListener, TextListener
Classes: java.util.EventListenerProxy, AWTEventListenerProxy, KeyAdapter,
ComponentAdapter, ContainerAdapter, MouseAdapter, FocusAdapter,
MouseMotionAdapter, HierarchyBoundsAdapter, WindowAdapter
Events
http://www.falkhausen.de/en/diagram/html/java.awt.event.Events.html
Interfaces: java.awt.ActiveEvent
Classes: InputMethodEvent, java.awt.AWTEvent, java.util.EventObject,
HierarchyEvent, InvocationEvent, TextEvent, ActionEvent, ItemEvent,
AdjustmentEvent, ComponentEvent, PaintEvent, FocusEvent,
InputEvent, WindowEvent, ContainerEvent, MouseEvent, KeyEvent,
MouseWheelEvent, java.awt.AWTKeyStroke, javax.swing.KeyStroke
java.awt.event.* Class Diagram
cont’d
Support
http://www.falkhausen.de/en/diagram/html/java.awt.event.E
ventSupport.html
Classes: java.awt.AWTEventMulticaster,
java.awt.EventQueue
javax.swing.* Class Diagrams
Components
Hierarchy
JComponent
Labels
Slider+Progress
Spinner
CellEditor
CellRenderer
Container
RootpaneContainer
Panes
Scrolling
Layers
Classes: javax.swing.JComponent
javax.swing.* Class Diagrams cont’d
Container
RootpaneContainer
Panes
Scrolling
Layers
Dialogs
JOptionPane
JFileChooser
JColorChooser
javax.swing.* Class Diagrams cont’d
Button+Menu
Buttons
ButtonModel
MenuSupport
MenuEvents
Lists
List+Combo
ListModel
ListEvent
Lists
List+Combo
ListModel
ListEvent
javax.swing.* Class Diagrams cont’d
Action
LookAndFeel
Utilities
Exceptions
javax.swing.border
javax.swing.event
Listener
Events
javax.swing.plaf
ComponentUI
UIResource
javax.swing.table
JTable
TableModel
Support
Events
javax.swing.* Class Diagrams cont’d
javax.swing.text
TextComponents
Formatter
Document
EditorKit
AttributeSet
View
Element
Position
Caret
AbstractWriter
Utilities
Events
javax.swing.* Class Diagrams cont’d
javax.swing.text.html
HTMLDocument
HTMLEditorKit
StyleSheet
Views
HTML
Parsing
javax.swing.text.html.parser
javax.swing.tree
JTree
TreeModel
TreeNode
Events
javax.swing.undo
http://www.falkhausen.de/en/diagram/spec/javax.swing.html
General Approach to JAVA 2D API
Transition from the Graphics object to a
Graphics2D object
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Typical Swing approach
Graphics2D g2d = (Graphics2D)g;
g2d.doSomeWork(...);
... }
Create a Shape object
Rectangle2D.Double rect = ...;
Ellipse2D.Double ellipse = ...;
Polygon poly = ...;
GeneralPath path = ...;
SomeShapeYouDefined shape = ...;
// Satisfies Shape interface ...
General Approach to JAVA 2D API
cont’d
Optional: modify drawing parameters
g2d.setPaint (fillColorOrPattern);
g2d.setStroke (penThicknessOrPattern);
g2d.setComposite (someAlphaComposite);
g2d.setFont(someFont);
g2d.translate(...);
g2d.rotate(...);
g2d.scale(...);
g2d.shear(...);
g2d.setTransform(someAffineTransform);
Draw an outlined or solid version of the Shape
g2d.draw(someShape);
g2d.fill(someShape);
Example: Drawing Shapes
import javax.swing.*; // For JPanel
import java.awt.*; // For Graphics
import java.awt.geom.*; // For Ellipse2D
public class ShapeExample extends JPanel {
private Ellipse2D.Double circle = new Ellipse2D.Double(10, 10, 350, 350);
private Rectangle2D.Double square = new Rectangle2D.Double(10, 10, 350, 350);
import javax.swing.*
; import java.awt.*;
public class WindowUtilities {
/** Tell system to use native look and feel, as in previous * releases. Metal
(Java) LAF is the default otherwise. **/
public static void setNativeLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
System.out.println ("Error setting native LAF: " + e);
}
}
/** A simplified way to see a JPanel or other Container.
* Pops up a JFrame with specified Container as the content pane.
*/
public static JFrame openInJFrame (Container content, int width, int height, String title,
Color bgColor) {
JFrame frame = new JFrame (title);
frame.setBackground (bgColor);
content.setBackground (bgColor);
frame.setSize (width, height);
frame.setContentPane (content);
frame.addWindowListener (new ExitListener());
frame.setVisible(true);
return(frame);
}
/** Uses Color.white as the background color.
public static JFrame openInJFrame(Container content, int width,
int height, String title)
{
return(openInJFrame(content, width, height, title, Color.white));
}
/** Uses Color. white as the background color, and the
* name of the Container's class as the JFrame title. */
public static JFrame openInJFrame(Container content, int width, int height)
{ return(openInJFrame(content, width,
height,content.getClass().getName(),
Color.white));
}}
ExitListener.java
A WindowListener with support to close the window
import java.awt.*;
import java.awt.event.*;
Filling a Shape
A Color (solid color): Color.red, Color.yellow
A GradientPaint (gradient fill gradually
combining two colors)
Constructors takes two points, two colors, and
optionally a boolean flag that indicates that the
color pattern should cycle.
A TexturePaint (tiled image), or
A new version of Paint that we write ourselves
Use setPaint and getPaint to change and
retrieve the Paint settings.
setPaint and getPaint supersede the setColor and getColor
methods in Graphics.
Example: Gradient Fills
import java.awt.*;
public class GradientPaintExample extends ShapeExample
{ // Red at (0,0), yellow at (175,175), changes gradually between.
private GradientPaint gradient = new GradientPaint(0, 0, Color.red,
175, 175, Color.yellow, true);
// true means to repeat pattern
public void paintComponent(Graphics g) {
clear(g);
Graphics2D g2d = (Graphics2D)g;
drawGradientCircle(g2d);
}
protected void drawGradientCircle (Graphics2D g2d) {
g2d.setPaint(gradient);
g2d.fill(getCircle());
g2d.setPaint(Color.black);
g2d.draw(getCircle()); }
public static void main(String[] args) {
WindowUtilities.openInJFrame(new GradientPaintExample(), 380, 400); } }
Stroke Attributes
Each of the shapes drawn by the applet is constructed from one of the
The rectHeight and rectWidth variables define the dimensions of the space
where each shape is drawn, in pixels. The x and y variables change for each
shape so that they are drawn in a grid formation.
//draw Line2D.Double
g2.draw (new Line2D.Double(x, y+rectHeight-1, x + rectWidth, y));
g2.drawString("Line2D", x, stringY);
// draw Rectangle2D.Double
g2.setStroke(stroke);
g2.draw(new Rectangle2D.Double(x, y, rectWidth, rectHeight));
g2.drawString("Rectangle2D", x, stringY);
// draw RoundRectangle2D.Double
g2.setStroke(dashed);
g2.draw(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)
g2.drawString("RoundRectangle2D", x, stringY);
Stroke Attributes cont’d
// draw Arc2D.Double
g2.setStroke(wideStroke);
g2.draw(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135,
Arc2D.OPEN));
// draw Ellipse2D.Double
g2.setStroke(stroke);
g2.draw (new Ellipse2D.Double(x, y, rectWidth, rectHeight));
Drawing GeneralPath (polygon)
int x1Points[] = {x, x+rectWidth, x, x+rectWidth};
int y1Points[] = {y, y+rectHeight, y+rectHeight, y};
GeneralPath polygon = new
GeneralPath(GeneralPath.WIND_EVEN_ODD,
x1Points.length);
polygon.moveTo(x1Points[0], y1Points[0]);
for (int index = 1; index < x1Points.length; index++)
{
polygon.lineTo(x1Points[index], y1Points[index]);
};
polygon.closePath();
g2.draw(polygon);
Drawing GeneralPath (polyline)
int x2Points[] = {x, x+rectWidth, x, x+rectWidth};
int y2Points[] = {y, y+rectHeight, y+rectHeight, y};
GeneralPath polyline = new
GeneralPath(GeneralPath.WIND_EVEN_ODD,
x2Points.length);
polyline.moveTo (x2Points[0], y2Points[0]);
for (int index = 1; index < x2Points.length; index++) {
polyline.lineTo(x2Points[index], y2Points[index]);
};
g2.draw(polyline);
Stroke Attributes cont’d
// fill Rectangle2D.Double (red)
g2.setPaint(red);
g2.fill(new Rectangle2D.Double(x, y, rectWidth,rectHeight));
// fill RoundRectangle2D.Double
g2.setPaint(redtowhite);
g2.fill(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight,
10, 10));
// fill Arc2D g2.setPaint(red);
g2.fill(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135,
Arc2D.OPEN));
Using the Java 2D APIs to define
and render the Graphics and Text
public class ShapesDemo2D extends JApplet {
final static int maxCharHeight = 15;
final static int minFontSize = 6;
final static Color bg = Color.white;
final static Color fg = Color.black;
final static Color red = Color.red;
final static Color white = Color.white;
final static BasicStroke stroke = new BasicStroke(2.0f);
final static BasicStroke wide Stroke = new BasicStroke(8.0f);
final static float dash1[] = {10.0f}
final static BasicStroke dashed = new BasicStroke(1.0f,
BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER,
int x = 5;
int y = 7;
int rectWidth = gridWidth - 2*x;
int stringY = gridHeight - 3 - fontMetrics.getDescent();
int rectHeight = stringY - fontMetrics.getMaxAscent() - y - 2;