0% found this document useful (0 votes)
40 views

Java 2 D

The Java 2D API provides tools for 2D graphics rendering and manipulation. It includes classes for shapes, colors, transformations, compositing, and more. Graphics are rendered through a pipeline that handles rasterization, transformations, and compositing. The API supports common shapes, colors, coordinate systems, and drawing operations needed for 2D graphics applications.

Uploaded by

Sri Sumarni
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views

Java 2 D

The Java 2D API provides tools for 2D graphics rendering and manipulation. It includes classes for shapes, colors, transformations, compositing, and more. Graphics are rendered through a pipeline that handles rasterization, transformations, and compositing. The API supports common shapes, colors, coordinate systems, and drawing operations needed for 2D graphics applications.

Uploaded by

Sri Sumarni
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 86

Java 2D API

Provides

A uniform rendering model for display devices and printers


A wide range of geometric primitives
Mechanisms for performing hit detection on shapes, text, and images
A compositing model
Enhanced color support that facilitates color management
Support for printing complex documents

Most importantly it is the building blocks to your own custom


components.

Rendering process
Graphics2D

Graphics
Primitives

Shapes
Text
Images

Transformation

fill()
stroke

draw()

font

DrawString()
drawImage()

Rendering hints
rasterizer
Clipping shape

paint
images

Compositing rule

Output
Devices

2D Graphics
The Java 2D API enables you to control

Line Thickness
Fills
Move, rotate, scale, and shear text and graphics
Composites

Allows for complex graphics (Charts, overlays, etc)


The Java 2D API also enables you to store and to manipulate image
data
Blur
Sharpen

The Java 2D APIs are closely integrated with the Abstract Windowing
Toolkit (AWT).

Coordinate Spaces
Java 2D objects live in User Space, defined by Cartesian coordinates
Objects rendered to an output device are transformed into Device
Space for that device.
Usually one unit of device space corresponds to one pixel on the device.

Default transformations converts 72 pixels to one inch (typical screen


resolution)
Default transformation has physical screen size equal physical print
size

The Rasterizer
Inside the rendering pipeline, the rasterizer takes ideal shapes within
your program and produces coverage values for each pixel on a
display device.
The coverage values represent how much of each pixel is covered by
the shape.
These coverage values are called alpha values.
The alpha value indicates the transparency of the color itself.
Alpha values range from 0.0 to 1.0, 0.0 being fully transparent, 1.0
being fully opaque.
Anti-aliased shapes often have pixels with non 0.0/1.0 values at their
edges

Compositing is used to decide how to translate alpha values into color


information
Compositing determines how the colors of a new graphics primitive
are combined with the existing colors on a drawing surface.

Drawing Shapes
Except for Point2D and Dimension2D, each of the geometry classes
implements the Shape interface.
With these classes you can create virtually any geometric shape and
render it through Graphics2D by calling the draw method or the fill
method.
To draw someShape
g2d.draw(someShape);
g2d.fill(someShape);

Painting in Java
In AWT, painting was done in the paint(Graphics g) method of a
java.awt.Canvas
In Swing, you will do painting in the paintComponent(Graphics g)
method of a javax.swing.JComponent
JComponents paint() method now calls paintComponent(),
paintBorder() and paintChildren()
Changes to the Graphics2D object within paint stay within the
paintComponent() method.
With the exception of Rendering Hints

Drawing Shapes: Overview


With the AWT, you generally drew a shape by calling the drawXxx or
fillXxx methods of the Graphics object. In Java2D, you generally
create a Shape object, then call either the draw or fill method of the
Graphics2D object, supplying the Shape object as an argument. Youll
still want drawString and drawImage, however. Heres an example of
the normal approach:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
// Assume x, y, and diameter are instance variables
Ellipse2D.Double circle =
new Ellipse2D.double(x, y, diameter, diameter);
g2d.fill(circle);
...
}

SimpleShapes.java

Note rough edge to drawing

Colors in Java 2

Color is found in java.awt package


Primarily unchanged through different AWT/Swing versions
It is a class to encapsulate colors in the default sRGB color space
Multiple Constructors
Color(float r, float g, float b,)
Color(float r, float g, float b, float a)
Color(int rgb)
Red in bits 16-23
Green in bits 8-15
Blue in bits 0-7

Color(int r, int g, int b)


Color(int r, int g, int b, int a)

SystemColors
JFC allows you to set colors relative to desktop
Use UIManager.getColor(String itemName) to pull the current look and
feel colors into your application
For Example, if you wanted to set the background of your window to
the default background on the look and feel you are using, you would
use
setBackground(UIManager.getColor(window))

Use these instead of the explicit Color objects whenever possible


Sample values can be found in MetalLookAndFeel.java, but they work
in any of the Look and Feels

Color keys

"desktop - Color of the desktop background


"activeCaption" - Color for captions (title bars) when they are active.
"activeCaptionText" - Text color for text in captions (title bars).
"activeCaptionBorder" - Border color for caption (title bar) window
borders.
"inactiveCaption" - Color for captions (title bars) when not active.
"inactiveCaptionText" - Text color for text in inactive captions (title
bars).
"inactiveCaptionBorder" - Border color for inactive caption (title bar)
window borders.
"window - Default color for the interior of windows
"windowBorder - Border of window
"windowText - Text color of window
"menu - Background color for menus
"menuText - Text color for menus

More Color keys

"text - Text background color


"textText - Text foreground color
"textHighlight - Text background color when selected
"textHighlightText - Text color when selected
"textInactiveText - Text color when disabled
"control - Default color for controls (buttons, sliders, etc)
"controlText - Default color for text in controls
controlHighlight - Specular highlight (opposite of the shadow)
"controlLtHighlight - Highlight color for controls
"controlShadow - Shadow color for controls
"controlDkShadow - Dark shadow color for controls
"scrollbar - Scrollbar background (usually the "track")
"info - ToolTip Background
"infoText - ToolTip Text

Classes in the java.awt.geom package

Point2D
Arc2D
Area
CubicCurve2D
Dimension2D
Ellipse2D
GeneralPath

Points
A point is not a pixel
Point2D is an abstract class
Contains inner children
Point2d.Float and Point2D.Double

Point is still left over from AWT 1.0, holds coordinates as integers
Point2D includes methods for calculating the distance between two
points
public double distance (double PX, double PY)
public double distance (Point2D pt)

Why floats and doubles?

Shapes
Common interface implemented by several classes with 2D package
Four groups of methods in interface
getBounds()
contains
(x,y), Point2D, Rectangle2D

intersects()
(x,y,w,h) and Rectangle2D

getPathIterator()

Each Shape has a set of segments

move
line
quad
cubic
close

Winding Rules
If you fill an abstract shape, how does it get filled?
A winding rule determines what part of a shape is defined as the
interior, and consequently what part of the shape will be filled by a
call to fill()
Even-odd rule
Draw a line through the entire shape
Each time the line crosses the shapes border, increment a counter
When the counter is even, the line is outside the shape, odd is in

Non-zero (overlapping)
Draw a line through the entire shape
As line crosses each edge a +1 is counted for edges drawn from left to
right, -1 for right to left
Non zero regions are considered the interior of the shape

Winding Rules Illustrated

1 2

4
3

Even-odd

-1
0

-1 -2

Non-zero

GeneralPath
Allows you to build a path, segment by segment
public GeneralPath()
Uses non-zero as default winding rule

public GeneralPath(int windingRule)


public GeneralPath(int windingRule, int InitialCapacity)
Use initial capacity if you are worried about performance

Common methods

moveTo(float x, float y)
lineTo(float x, float y)
quadTo(float controlX1, float controlY1, float endX, float endY)
cubicTo(float controlX1, float controlY1, float controlX2, float
controlY2, float endX, float endY)
append(Shape s, boolean connect)
closePath()

Lines and Curves


Line2D
Lines take doubles, floats, and Point2Ds as arguments
setLine(Line2D line) sets the endpoint of the line to be the same as the
given line

QuadCurve2D
doubles and Point2Ds as arguments

CubicCurve2D
doubles and Point2Ds as arguments

Rectangles
RectangularShape is an abstract class that is used in several children
Supplies some common methods

getX, getY, getWidth, getHeight, getMaxX.


getCenterX, getCenterY
setFrame() sets the bounds of a rectangle using x, y, w, and h
setFrameFromDiagonal() also sets the bounds using two points

Rectangle2D
Double and Float versions
boolean intersectsLine() sees if a line intersects a Rectangle2D
public int outcode(Point2D)
masked integer which holds combination of OUT_TOP, OUT_BOTTOM,
OUT_LEFT and OUT_RIGHT

The Rectangle from AWT is still around, and is a subclass of


Rectangle2D

Round Rectangles, Ellipses and Arc


RoundRectangle
You specify the width and the height of the arc in the constructor

Ellipse2D
Ellipse specified by a rectangle

Arc2D

Three closure options, OPEN, PIE, and CHORD


Specified by x, y, w, h, angleStart, angleExtent, closure
Also specified by Point2D/Dimension2D and by Rectangle2D
setArcByCenter(double x, double y, double r, double angleStart, double
angleExtent)

Constructive Area Geometry


Allows you to build complex shapes by combining simple shapes

addition
intersection
subtraction
exclusive or

You create an Area, usually empty at first, and work from there
Area is just another implementation of the Shape interface

Original
Shapes

addition

intersection subtraction

Xor

Line Styles
Used when drawing an object
Line styles are defined by the stroke attribute in the Graphics2D
rendering context.
A BasicStroke object holds information about the line width, join
style, end-cap style, and dash style.
The line width is the thickness of the line measured perpendicular to its
trajectory. The line width is specified as a float value in user coordinate
units, which are roughly equivalent to 1/72 inch when the default
transform is used.

Join Styles and End Caps


BasicStroke supports three join styles:
JOIN_BEVEL
JOIN_MITER
JOIN_ROUND

The end-cap style is the decoration that is applied where a line


segment ends. BasicStroke supports three end-cap styles:
CAP_BUTT
CAP_ROUND
CAP_SQUARE

Dash Styles
The dash style defines the pattern of opaque and transparent sections
applied along the length of the line.
The dash style is defined by a dash array and a dash phase.
The dash array defines the dash pattern.
The dash phase is an offset into the dash pattern

Note that join styles and end caps apply to individual dashes in a dash
style

BasicStroke object
Constructors
public BasicStroke(float width,
int cap,
int join,
float miterlimit,
float[] dash,
float dash_phase)
public BasicStroke(float width,
int cap,
int join,
float miterlimit)
public BasicStroke(float width,
int cap,
int join)
public BasicStroke(float width)
public BasicStroke()

Code Example, SimpleStroke.java

Fill Patterns in Java2D:


Overview
When you fill a Shape, the current Paint attribute of the Graphics2D object is used. This
can be

a Color (solid color),


a GradientPaint (gradient fill gradually combining two colors),
a TexturePaint (tiled image), or
a new version of Paint that you write yourself.

Use setPaint and getPaint to change and retrieve the Paint settings.
Note that setPaint and getPaint supersede the setColor and getColor methods that were
used in Graphics (and inherited in Graphics2D).
Arguments to the Graphics2D setPaint method (and return values of getPaint) must
implement the Paint interface. Here are the major built-in Paint classes:
Color
GradientPaint
TexturePaint

Gradient Fills
Use GradientPaint class from java.awt package
The GradientPaint class provides a way to fill a Shape with a linear
color gradient pattern.
Given a starting point P1 with Color C1, and an ending point P2 with a
color C2
If the gradient is cyclic then the points on the extended P1, P2 connecting
line cycle back and forth between the colors C1 and C2.
If the gradient is acyclic then points on the P1 side of the segment have
the constant Color C1 while points on the P2 side have the constant Color
C2.

Code Example, GradientExample.java

Code Example, GeneralPaths.java

Code Example, GeneralPaths3.java

Tiled Images as Fill Patterns


Create a TexturePaint Object. TexturePaint Constructor Takes:
A BufferedImage (see following pages)
Specifies what to draw

A Rectangle2D
Specifies how big the tiled image is

Specify its use via the setPaint method of Graphics2D


You can get a Buffered Image in two basic ways
Use ImageIO class of JDK 1.4
Build it with a GIF

Use ImageIO class of JDK 1.4


The javax.imageio.ImageIO class provides a set of static convenience
methods that perform most simple Image I/O operations.
Reading an image that is in a standard format (GIF, PNG, or JPEG) is
simple:
File f = new File("c:\images\myimage.gif");
BufferedImage bi = ImageIO.read(f);

The set of formats available for reading can be obtained by calling


ImageIO.getReaderFormatNames.
This will return an array of Strings containing the names of the available
formats, such as "gif" and "png."

Writing an image in a supported format is equally simple:


BufferedImage bi;
File f = new File("c:\images\myimage.png");
ImageIO.write(im, "png", f);

Using the BufferedImage


Once you have the BufferedImage, you then can use it as follows
// imageRect is the area that the image will be mapped to
imageRect =
new Rectangle2D(0.0, 0.0, bufferedImage.getWidth(),
bufferedImage.getHeight());
imagePaint1 =
new TexturePaint(bufferedImage, imageRect);

Note that the Rectangle2D object can be set to the image size, creating
an image tile the same size as the original image, or it could be set to a
different dimension

Code Example, TiledImages.java

Old Method 1: Building a Buffered Image with a GIF


First you need a Media Tracker to load the image
The MediaTracker class is a utility class to track the status of a number
of media objects. Media objects could include audio clips as well as
images, though currently only images are supported
To use a media tracker, create an instance of MediaTracker and call its
addImage method for each image to be tracked. In addition, each
image can be assigned a unique identifier. This identifier controls the
priority order in which the images are fetched. It can also be used to
identify unique subsets of the images that can be waited on
independently. Images with a lower ID are loaded in preference to
those with a higher ID number.

Using Media Trackers


Used to Load an Image from an image file,
Use MediaTracker to be sure it is done loading,
Image image = c.getToolkit().getImage(imageFile);
MediaTracker tracker = new MediaTracker(c);
tracker.addImage(image, 0);
try {
tracker.waitForAll();
} catch(InterruptedException ie) {}
if (tracker.isErrorAny() return null);

Note the use of public void waitForAll()


Starts loading all images tracked by this media tracker. This method waits
until all the images being tracked have finished loading.
If there is an error while loading or scaling an image, then that image is
considered to have finished loading. Use the isErrorAny or isErrorID
methods to check for errors.

BufferedImage class
Once we have loaded an image, we need to place it into a
BufferedImage class
BufferedImage
The immediate-mode imaging model enables you to manipulate and
display pixel-mapped images whose data is stored in memory. You can
access image data in a variety of formats and use several types of filtering
operations to manipulate the data.
BufferedImage is the key class in the immediate-mode imaging API. This
class manages an image in memory and provides methods for storing,
interpreting, and rendering the pixel data. A BufferedImage can be
rendered through either a Graphics or a Graphics2D rendering context.
A BufferedImage is essentially an Image with an accessible data buffer. A
BufferedImage has a ColorModel and a Raster of image data.

Tiling with Buffered Images (GIF)


Create an empty BufferedImage using the Image width and height,
Get the Graphics2D via createGraphics,
Draw the Image onto the BufferedImage.
Image

image = getToolkit().getImage(imageFile);
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(image, 0);
try {
tracker.waitForAll();
} catch(InterruptedException ie) {}
if (tracker.isErrorAny()) return;
BufferedImage bufferedImage =
new BufferedImage(image.getWidth(this), image.getHeight(this),
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedImage.createGraphics();
g2d.drawImage(image, 0, 0, this);

Old Method 2, Building a BufferedImage using a GIF


A MediaTracker starts a new thread, which loads images. When
they are all loaded, the thread notifies the calling thread that it is done,
and the original thread continues
Swing offers the ImageIcon class, your one stop shop for creating
Images.
Image image = new ImageIcon(duke.gif).getImage()

You still need to create the BufferedImage, but you dont need to
mess with the MediaTracker code for a single image.

Fonts
Cornerstone of 2D APIs text rendering system
Fonts can have three different names
Family name
Face name(Font name)
Garamond Italic is a font face name for a font whose family is Garamond

Logical names
Used before the 2D API to uniquely identify fonts.
Toolkits getFontList() returns a list of logical fonts
Deprecated method in JDK 1.2

Guaranteed to be on every system


Mapped to local fonts on each system
Serif maps to Times New Roman on WinNT

Dialog
DialogInput
Serif
SansSerif
ZapfDingbats
Monospaced

Available Fonts
Of course there are a few idiosyncrasies
Logical fonts exist, and are mapped to local fonts using the font.properties
file in the jre/lib directory
There is a set of Physical Fonts, these are located in the jre/lib/fonts
subdirectory of the JDK installation. They are available on any platform
with Java2 installed. Each family has a Regular, Bold, Oblique and Bold
Oblique style

Lucida Sans family


Lucida Bright family
Lucida Sans Typewriter family.
If only the JRE for Java2 is installed, only the Lucida Sans Regular font is
provided. (This particularly applies to plug-in usage)

Getting access to local fonts is not obvious

Local Fonts
First you need a GraphicsEnvironment instance that represents your
system.
GraphicsEnvironment.getLocalGraphicsEnvironment()

You can then get an array of every font installed in your system with
the public Font[] getAllFonts() method
This can take a lot of time. Some systems may have hundreds of fonts,
and when you call this method, you get to wait for a bit.

You can also get just the names of Fonts, (not the Fonts themselves)
with the public String[] getAvailableFontFamilyNames()
method instead, which is much faster.

Example: Loading a Local Font


Lets say you have a local font on your system called Alladin
Step 1: Get the local graphics environment
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();

Step 2: If you want to use the Font.getFont(Alladin) method,


you will need to call ge.getAllFonts() first, or it will return null.
Step 2 alternate: You could use the much faster
ge.getAvailableFontFamilyNames()

Printing Out All Local Font Names


// From Fonts.java
GraphicsEnvironment en =
GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames =
en.getAvailableFontFamilyNames();
System.out.println("Available Fonts:");
for(int i=0; i<fontNames.length; i++)
System.out.println(" " + fontNames[i]);
}
}

Loading Dynamic Fonts


The new method Font.createFont(int, InputStream) provides the ability to
add fonts to the Java 2 Virtual Machine (JVM) at runtime. This font is not
persistent upon termination of the JVM and is only available to the creator
of the Font.
At this time, only TrueTypeTM fonts can be created at runtime.
The following code sample illustrates how to dynamically load the
TrueType font Arial from a file (DynamicFont.java):
File file = new File("Arial.ttf");
FileInputStream fis = new FileInputStream(file);
Font font = Font.createFont(Font.TRUETYPE_FONT, fis);

Getting Information on a Font


FontMetrics
In old AWT, you would pass a Font to the Toolkits getFontMetrics()
method
It has been replaced with the java.awt.font.LineMetrics and
java.awt.font.FontRenderContext classes
You can get a string bounds from a font using its
getStringBounds(String, FontRenderContext) method
You now ask a Font for a LineMetrics object by calling one of its
getLineMetrics() methods

FontRenderContextClass
When the rendering engine renders text, the results depend on the engines
transform and rendering hints
KEY_ANTIALIASING
KKEY_FRACTIONAL_METRICS

You need to pass this information to the getLineMetrics() method and


getStringBounds()

More Information on a Font


One you have a FontRenderContext
You can get the the bounds of a string with public Rectangle2D
getStringBounds().
Takes String, char[], or CharacterIterator index
FontRenderContext
String title = Hello World;
titleFont = new Font("Sans Serif", Font.PLAIN, 24);
fontRenderContext = new FontRenderContext(new AffineTransform(),
true, false);
titleFontBounds = titleFont.getStringBounds(title, fontRenderContext);

LineMetrics Class
Provides, ascent, descent, leading, height values for fonts

Text
2D API offers several options for rendering Text

Use a Swing component (JTextField, JTextArea, or JEditorPane).


Pass a character string to one of Graphics2Ds drawString() methods
Use TextLayout
Glyph Level manipulation
drawString(String str, int x, int y)
drawString(String str, double x, double y)

x and y are the location of the strings baseline


Note that fractional pixel coordinates are not used by renderer, they
are converted to ints
Allows caching of glyphs - performance and continuity enhancement, this
is also called grid fitting

Styled text
You can render styled text using an AttributedString and its
corresponding AttributedCharacterIterator.
First Create an AttributedString
AttributedString aString = new AttributedString(Foo Bar Baz)

Second, add attributes to the AttributedString.


Use the java.awt.font.TextAttribute class to get key values

Third get the AttributedCharacterIterator from the


AttributedString
Fourth, pass the iterator to drawString()
drawString(AttributedCharacterIterator iterator, int x,
int y)

You can even embed graphics within a StyledString if you replace


characters with graphics.

Code Example, StyledString.java

TextLayout
drawString() renders simple pieces of code
TextLayout class supports

Text metrics
Hit testing
Caret Support
Highlighting support
Paragraph Layout on Multiple lines
Font Outline
Bi-directional text

TextLayout objects use


Text
Font
FontRenderContext

To Render you use public void draw(Graphics 2D g2d,


float x, float y)

Text Layout features


Hit Testing
Given a set of coordinates, you can get a java.awt.font.TextHitInfo object
This is a logical character index, plus additional information (leading,
trailing)

Caret support
Wont draw a Caret, but gives you the information you need to draw one
yourself

Highlighting
Helps you calculate shapes you need to draw a highlight

Code Example, Highlighting.java


This is a good example of other
features Swing gives you.
Both show TextLayout and
Highlighting
First uses Frame and paint() from
Java2D text
Second is modified to use JFrame
and paintComponent()
Only when you run the code, do
you see the major differences

TextLayout and Multiline text


If you use java.awt.font.LineBreakMeasurer, you can have TextLayout
dynamically lay out multiline text
LineBreakMeasurer uses an AttributedCharacterIterator and
FontRenderContext to break up a string into individual lines
Uses public TextLayout nextLayout() method to parse the string into
individual TextLayout objects

Code Example ParagraphLayout.java

To use TextLayout for Font Outlines


First, create one using a String, Font, and FontRenderContext
FontRenderContext is used to get info on a Rendered Font

Next you need to get the outline of the font


AffineTransform textAt = new AffineTransform();
textAt.translate(0, (float)textTl.getBounds().getHeight());
textShape = textTl.getOutline(textAt);

Then you can draw into the shape


Code Example, TiledImages2.java

Transparency of objects
Java2D permits you to assign transparency (alpha) values to drawing
operations so that the underlying graphics partially shows through
when you draw shapes or images.
To Create an AlphaComposite object
Call AlphaComposite.getInstance with a mixing rule designator and a
transparency (or "alpha") value.
There are 8 built-in mixing rules (see the AlphaComposite API for
details), but the one normally used for drawing with transparency settings
is AlphaComposite.SRC_OVER.
Alpha values range from 0.0f (completely transparent) to 1.0f
(completely opaque).

Alpha and Compositing


Rendering is an approximation.
When you ask to have an ideal shape filled, the rendering engine
figures out how the pixels of an output device should be colored to
best approximate the shape.
Speed vs. quality
Fast method (aliasing)
color the pixels whose centers fall within the shape. With this algorithm,
pixels are either colored or not.

Quality method (anti-aliasing)


Calculate the intersection of the shape with each pixel of the output
device.
Pixels are colored in proportion to the amount they are covered by the
shape.

Code Example, Alpha1.java

Dont use anti-aliasing


for standard size screen
fonts. It will actually
reduce legibility.
Standard screen fonts
have been optimized for
their size

Enlarges to...

Code Example, Alpha2.java


A Larger Font Enlarges to...

Code Example, Transparency. java


Two ways of painting a
transparency
Make a normal Color object and then
call setPaint() and setComposite()
Make a Color object with RGB and A
values, then just call setPaint().
Color(intr, intg, intb, inta)

Coordinate Transformations
AffineTransformations - parallel lines are still parallel after
transformation
Graphics2D has an internal transformation that it applies to any
graphics device
You can modify or set this transform with
public setTransform(AffineTransform at)
public transform(AffineTransform at)

You have two options when transforming things


Transform the coordinate system
Transform the shape

AffineTransformations
Embodies a mathematical concept that allows points to be transformed
into other points.
Uses 3x3 matrices to manipulate images
Note that with matrix multiplication AxB != BxA
All Graphics2D objects have a default, identity transform. This
transform should be used to reset the Graphics2D object when you are
done with the transform.
This object is used to transform coordinates from the user space (0,0) at
top left of window, to coordinates in the device space
Devices may be screens, printers, etc.

Remember that the Graphics2D transform is applied to all rendering


operations and attributes. That is the transform applies for drawing
and filling Shapes, drawing Images, and text. Paint and Stroke objects
are also affected

Transforming the Coordinate System


Idea:
Instead of computing new coordinates, move the coordinate system itself.

Available Transformations

Translate (move)
Rotate (spin).
Scale (stretch evenly)
Shear (stretch more as points get further from origin -- see example)
Custom. New point (x2, y2) derived from original point (x1, y1) as
follows:

[ x2]
[
[ y2] = [
[ 1 ]
[

m00
m10
0

m01
m11
0

m02
m12
1

] [ x1 ]
[ m00x1 + m01y1 + m02 ]
] [ y1 ] = [ m10x1 + m11y1 + m12 ]
] [ 1 ]
[
1
]

Applying:

Call translate, rotate, scale, or shear on Graphics2D object


Create an AffineTransform and apply it via setTransform or transform
Remember, it is the coordinate system that is moving underneath the object
you are printing

Types of Transforms
Translation
public void translate(double tx, double ty)
adds translation to an AffineTransform

public static AffineTransform getTranslateInstance(double tx, double ty)


Makes a new AffineTransform

Rotation
public void rotate(double thetaRadians)
public void rotate(double thetaRadians, double x, double y)
Rotate around (x,y) not origin

getRotateInstance(...) methods similar to above

Scaling
Line thickness is scaled. If you dont want this to happen, dont modify
the Graphics2D object, modify the shapes themselves
If you pass negative values, you can switch the direction of the axis
public void scale(double sx, double xy)
getScaleInstance()

Code Example, Rotate.java

Transforming shapes
public Shape createTransformedShape(Shape pSrc)
Uses an existing AffineTransform and transforms a given Shape and
returns the result as another Shape

Shear Transformations
Meaning of Shear
X Shear
If you specify a non-zero x shear, then x values will be more and more
shifted to the right the farther they are away from the y axis. For example,
an x shear of 0.1 means that the x value will be shifted 10% of the
distance the point is away from the y axis.
Y Shear
Points are shifted down in proportion to the distance they are away from
the x axis.

Code Example, Shear.java

Creating transformed shapes


You can use AffineTransforms to produce complex looking graphics
fairly easily.
Start with a base shape
Rotate
Scale
Transform

Create modified versions of a Font


Shear
Translate

Once you make a transformation, it can be applied to any Graphics2D


object

Code Example, Affine1.java

Rendering Hints
Default:
Faster drawing

Rendering Hints:
Let you request more accurate (but generally slower) drawing.
Example (highest quality):
RenderingHints renderHints =
new RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
...
public void paintComponent(Graphics g) {
// super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHints(renderHints);

Other Ways of Setting Rendering Hints


java -Dswing.aatext=true <YourMainClass.class>
turns on anti-aliasing for everything in your app
RenderingHints is one trait that is passed from a parent to a child
container
So, to turn on rendering hints for a container:

public void paint(Graphics g) {


Graphics2D g2d = (Graphics2D)g;
RenderingHints renderHints =
new
RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHints(renderHints);
super.paint(g2d);
}

In practice, the new RenderingHints would be a static final attribute on


the object, and not made new each time in a paint method.

Images
An Image is a two-dimensional array of colors. Each element is called
a pixel
java.awt.Image is effectively just a box for image data, you can read
from it, but not modify it.
You can load Images using a MediaTracker object, shown earlier
Original Graphics support in AWT supplied six methods to draw
images
One pair to draw at a given location
The second to draw scaled image
The third pair to draw into a clipped rectangle

Java 2D adds the following


One method to run the Image through an AffineTransform
One method to draw a processed BufferedImage.

Options on drawing Images


All of the 2D behaviors can be applied to drawing images
Transforms
Clipping
Alpha

If you make a BufferedImage, you can get a Graphics2D context from


that and draw directly on the image
Image Processing

Blurring
Sharpening
Edge Detecting
Posterizing
Inversion
Brightness
Color Conversions

Devices in Java2D
One goal of the 2D API is to make the rendering process the same,
regardless of the output device.
GraphicsEnvironment
Knows about fonts on your computer
Can access screen devices (GraphicsDevice class)
TYPE_RASTER_SCREEN
TYPE_PRINTER
TYPE_IMAGE_BUFFER

Default AffineTransforms

Printing
Tucked away in the java.awt.print package
Not to be confused with the AWT versions which are still included!
java.awt.PrintJob etc...

Key classes for printing


java.awt.print.PrinterJob
Controls the printing process, displays print dialog and page setup dialogs

java.awt.print.Printable
Interface represents something that can be printed, contains a single method,
print()

Printing Sequence
First a PrinterJob is instantiated by calling the
PrinterJob.getPrinterJob() method
The item to be printed is then passed to the PrinterJobs setPrintable()
method
A Print dialog is then shown
If the user presses ok, the printDialog() method returns true, and the
print job is started by calling the PrinterJob print() method
Control is returned to the application once the entire printing job has
been sent to the underlying OS.

The Printable Interface


Single method which must be implemented by object being printed

public int print(Graphics g, PageFormat pf, int


pageIndex) throws PrinterException

Called to render a page to a printer


You can cast the Graphics object to a Graphics2D object to take
advantage of 2Ds features
PageFormat describes the size and orientation of the paper
pageIndex is the number of the page to be printed

Should return PAGE_EXISTS if everything is ok, NO_SUCH_PAGE if


not
Declaring the exception in your method is optional

PageFormat class

Describes a sheet of paper and its orientation


0,0 is at top left
Imageable area is the part of the paper on which the printer can print
Three orientations
PORTRAIT
LANDSCAPE (0,0 at bottom left)
REVERSE_LANDSCAPE (0,0 at top right)

getWidth and getHeight methods return 1/72nd inches


8.5 x 11 is 612 x 792 units

PrinterJob class

No public constructor, use factory method


setPrintable(Printable paintable) sets the object to be printed
print() starts the print job
cancel() stops it as soon as possible, but needs to be in a separate
thread.
Showing Dialogs
printDialog() brings up options on printer, number of copies, and page
range.
If user selects OK, the method returns true

pageDialog() brings up options on page size and orientation


returns a PageFormat object.

Printing Swing components


JDK 1.2 had a lot of printing problems.
Swing containers automatically implement double buffering
The offscreen image that is used for double buffering has the same
resolution as the screen (typically 72dpi).
If you print to a 300 dpi printer, you effectively get a screen dump as pictured
in PrintTest1.java

All you need to do is disable double buffering during paint


In JDK1.3+, the double buffering problem is fixed! (PrintTest3.java)

Printing in the modern JDK


JComponent previously did not override print. This meant that printing
was no different than painting, resulting in the double buffer being
used by default.
To be consistent with the painting methods, methods printBorder,
printChildren and printComponent have been added, all of which are
protected.
This means that the print method of a JComponent does the following:
Invoke this method to print the receiver. This method will result in
invocations to printComponent, printBorder and printChildren.
It is not recommended that you override this method, instead override one
of the previously mentioned methods.
This method sets the receivers state such that the double buffer will not be
used, eg painting will be done directly on the passed in Graphics.

Code example, PrintTest3.java

Printing Multiple Pages

PrinterJob blindly call print interface in Printable object until

NO_SUCH_PAGE is returned.
All pages will have same page setup

Pageable interface
specifies a way to associate a PageFormat and a Printable with
each page of a print job.
java.awt.print.Book implements this interface

Downloads
Get the presentation at http://webdev.apl.jhu.edu/~
rbe/java/Java_2D/all.zip

You might also like