summaryrefslogtreecommitdiff
path: root/gnu/java/awt/java2d/AbstractGraphics2D.java
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/java/awt/java2d/AbstractGraphics2D.java')
-rw-r--r--gnu/java/awt/java2d/AbstractGraphics2D.java178
1 files changed, 133 insertions, 45 deletions
diff --git a/gnu/java/awt/java2d/AbstractGraphics2D.java b/gnu/java/awt/java2d/AbstractGraphics2D.java
index 326863163..da2125398 100644
--- a/gnu/java/awt/java2d/AbstractGraphics2D.java
+++ b/gnu/java/awt/java2d/AbstractGraphics2D.java
@@ -100,6 +100,20 @@ import java.util.Map;
* {@link #updateRaster(Raster, int, int, int, int)} method, which always gets
* called after a chunk of data got painted into the raster.
* </p>
+ * <p>Alternativly the backend can provide a method for filling Shapes by
+ * overriding the protected method fillShape(). This can be accomplished
+ * by a polygon filling function of the backend. Keep in mind though that
+ * Shapes can be quite complex (i.e. non-convex and containing holes, etc)
+ * which is not supported by all polygon fillers. Also it must be noted
+ * that fillShape() is expected to handle painting and compositing as well as
+ * clipping and transformation. If your backend can't support this natively,
+ * then you can fallback to the implementation in this class. You'll need
+ * to provide a writable Raster then, see above.</p>
+ * <p>Another alternative is to implement fillScanline() which only requires
+ * the backend to be able to draw horizontal lines in device space,
+ * which is usually very cheap.
+ * The implementation should still handle painting and compositing,
+ * but no more clipping and transformation is required by the backend.</p>
* <p>The backend is free to provide implementations for the various raw*
* methods for optimized AWT 1.1 style painting of some primitives. This should
* accelerate painting of Swing greatly. When doing so, the backend must also
@@ -126,6 +140,9 @@ import java.util.Map;
* in plain Java because they involve lots of shuffling around with large
* arrays. In fact, you really would want to let the graphics card to the
* work, they are made for this.</li>
+ * <li>Provide an accelerated implementation for fillShape(). For instance,
+ * OpenGL can fill shapes very efficiently. There are some considerations
+ * to be made though, see above for details.</li>
* </ol>
* </p>
*
@@ -144,6 +161,12 @@ public abstract class AbstractGraphics2D
private static final int AA_SAMPLING = 8;
/**
+ * Caches certain shapes to avoid massive creation of such Shapes in
+ * the various draw* and fill* methods.
+ */
+ private static final ThreadLocal shapeCache = new ThreadLocal();
+
+ /**
* The transformation for this Graphics2D instance
*/
protected AffineTransform transform;
@@ -184,11 +207,6 @@ public abstract class AbstractGraphics2D
private RenderingHints renderingHints;
/**
- * The paint raster.
- */
- private Raster paintRaster;
-
- /**
* The raster of the destination surface. This is where the painting is
* performed.
*/
@@ -219,7 +237,7 @@ public abstract class AbstractGraphics2D
* AbstractGraphics2D object and will be the most commonly used setting
* in Swing rendering and should therefore be optimized as much as possible.
*/
- private boolean isOptimized;
+ private boolean isOptimized = true;
/**
* Creates a new AbstractGraphics2D instance.
@@ -270,7 +288,6 @@ public abstract class AbstractGraphics2D
public boolean drawImage(Image image, AffineTransform xform,
ImageObserver obs)
{
- boolean ret = false;
Rectangle areaOfInterest = new Rectangle(0, 0, image.getWidth(obs),
image.getHeight(obs));
return drawImageImpl(image, xform, obs, areaOfInterest);
@@ -1144,14 +1161,31 @@ public abstract class AbstractGraphics2D
{
if (isOptimized)
{
- int tx = (int) transform.getTranslateX();
- int ty = (int) transform.getTranslateY();
- rawDrawLine(x1 + tx, y1 + ty, x2 + tx, y2 + ty);
+ rawDrawLine(x1, y1, x2, y2);
}
else
{
- Line2D line = new Line2D.Double(x1, y1, x2, y2);
- draw(line);
+ ShapeCache sc = getShapeCache();
+ if (sc.line == null)
+ sc.line = new Line2D.Float();
+ sc.line.setLine(x1, y1, x2, y2);
+ draw(sc.line);
+ }
+ }
+
+ public void drawRect(int x, int y, int w, int h)
+ {
+ if (isOptimized)
+ {
+ rawDrawRect(x, y, w, h);
+ }
+ else
+ {
+ ShapeCache sc = getShapeCache();
+ if (sc.rect == null)
+ sc.rect = new Rectangle();
+ sc.rect.setBounds(x, y, w, h);
+ draw(sc.rect);
}
}
@@ -1167,13 +1201,15 @@ public abstract class AbstractGraphics2D
{
if (isOptimized)
{
- int tx = (int) transform.getTranslateX();
- int ty = (int) transform.getTranslateY();
- rawFillRect(x + tx, y + ty, width, height);
+ rawFillRect(x, y, width, height);
}
else
{
- fill(new Rectangle(x, y, width, height));
+ ShapeCache sc = getShapeCache();
+ if (sc.rect == null)
+ sc.rect = new Rectangle();
+ sc.rect.setBounds(x, y, width, height);
+ fill(sc.rect);
}
}
@@ -1214,8 +1250,11 @@ public abstract class AbstractGraphics2D
public void drawRoundRect(int x, int y, int width, int height, int arcWidth,
int arcHeight)
{
- draw(new RoundRectangle2D.Double(x, y, width, height, arcWidth,
- arcHeight));
+ ShapeCache sc = getShapeCache();
+ if (sc.roundRect == null)
+ sc.roundRect = new RoundRectangle2D.Float();
+ sc.roundRect.setRoundRect(x, y, width, height, arcWidth, arcHeight);
+ draw(sc.roundRect);
}
/**
@@ -1231,8 +1270,11 @@ public abstract class AbstractGraphics2D
public void fillRoundRect(int x, int y, int width, int height, int arcWidth,
int arcHeight)
{
- fill(new RoundRectangle2D.Double(x, y, width, height, arcWidth,
- arcHeight));
+ ShapeCache sc = getShapeCache();
+ if (sc.roundRect == null)
+ sc.roundRect = new RoundRectangle2D.Float();
+ sc.roundRect.setRoundRect(x, y, width, height, arcWidth, arcHeight);
+ fill(sc.roundRect);
}
/**
@@ -1245,7 +1287,11 @@ public abstract class AbstractGraphics2D
*/
public void drawOval(int x, int y, int width, int height)
{
- draw(new Ellipse2D.Double(x, y, width, height));
+ ShapeCache sc = getShapeCache();
+ if (sc.ellipse == null)
+ sc.ellipse = new Ellipse2D.Float();
+ sc.ellipse.setFrame(x, y, width, height);
+ draw(sc.ellipse);
}
/**
@@ -1258,7 +1304,11 @@ public abstract class AbstractGraphics2D
*/
public void fillOval(int x, int y, int width, int height)
{
- fill(new Ellipse2D.Double(x, y, width, height));
+ ShapeCache sc = getShapeCache();
+ if (sc.ellipse == null)
+ sc.ellipse = new Ellipse2D.Float();
+ sc.ellipse.setFrame(x, y, width, height);
+ fill(sc.ellipse);
}
/**
@@ -1267,8 +1317,11 @@ public abstract class AbstractGraphics2D
public void drawArc(int x, int y, int width, int height, int arcStart,
int arcAngle)
{
- draw(new Arc2D.Double(x, y, width, height, arcStart, arcAngle,
- Arc2D.OPEN));
+ ShapeCache sc = getShapeCache();
+ if (sc.arc == null)
+ sc.arc = new Arc2D.Float();
+ sc.arc.setArc(x, y, width, height, arcStart, arcAngle, Arc2D.OPEN);
+ draw(sc.arc);
}
/**
@@ -1277,8 +1330,11 @@ public abstract class AbstractGraphics2D
public void fillArc(int x, int y, int width, int height, int arcStart,
int arcAngle)
{
- fill(new Arc2D.Double(x, y, width, height, arcStart, arcAngle,
- Arc2D.OPEN));
+ ShapeCache sc = getShapeCache();
+ if (sc.arc == null)
+ sc.arc = new Arc2D.Float();
+ sc.arc.setArc(x, y, width, height, arcStart, arcAngle, Arc2D.PIE);
+ draw(sc.arc);
}
public void drawPolyline(int[] xPoints, int[] yPoints, int npoints)
@@ -1292,7 +1348,13 @@ public abstract class AbstractGraphics2D
*/
public void drawPolygon(int[] xPoints, int[] yPoints, int npoints)
{
- draw(new Polygon(xPoints, yPoints, npoints));
+ ShapeCache sc = getShapeCache();
+ if (sc.polygon == null)
+ sc.polygon = new Polygon();
+ sc.polygon.xpoints = xPoints;
+ sc.polygon.ypoints = yPoints;
+ sc.polygon.npoints = npoints;
+ draw(sc.polygon);
}
/**
@@ -1300,7 +1362,13 @@ public abstract class AbstractGraphics2D
*/
public void fillPolygon(int[] xPoints, int[] yPoints, int npoints)
{
- fill(new Polygon(xPoints, yPoints, npoints));
+ ShapeCache sc = getShapeCache();
+ if (sc.polygon == null)
+ sc.polygon = new Polygon();
+ sc.polygon.xpoints = xPoints;
+ sc.polygon.ypoints = yPoints;
+ sc.polygon.npoints = npoints;
+ fill(sc.polygon);
}
/**
@@ -1461,8 +1529,12 @@ public abstract class AbstractGraphics2D
}
/**
- * Fills the specified shape. The shape has already been clipped against the
- * current clip.
+ * Fills the specified shape. Override this if your backend can efficiently
+ * fill shapes. This is possible on many systems via a polygon fill
+ * method or something similar. But keep in mind that Shapes can be quite
+ * complex (non-convex, with holes etc), which is not necessarily supported
+ * by all polygon fillers. Also note that you must perform clipping
+ * before filling the shape.
*
* @param s the shape to fill
* @param isFont <code>true</code> if the shape is a font outline
@@ -1534,6 +1606,11 @@ public abstract class AbstractGraphics2D
draw(new Line2D.Float(x0, y0, x1, y1));
}
+ protected void rawDrawRect(int x, int y, int w, int h)
+ {
+ draw(new Rectangle(x, y, w, h));
+ }
+
/**
* Draws a string in optimization mode. The implementation should respect the
* clip and translation. It can assume that the clip is a rectangle and that
@@ -1628,11 +1705,7 @@ public abstract class AbstractGraphics2D
}
/**
- * Fills the specified polygon. This should be overridden by backends
- * that support accelerated (native) polygon filling, which is the
- * case for most toolkit window and offscreen image implementations.
- *
- * The polygon is already clipped when this method is called.
+ * Fills the specified polygon without anti-aliasing.
*/
private void fillShapeImpl(ArrayList segs, Rectangle2D deviceBounds2D,
Rectangle2D userBounds,
@@ -1663,7 +1736,7 @@ public abstract class AbstractGraphics2D
for (Iterator i = segs.iterator(); i.hasNext();)
{
PolyEdge edge = (PolyEdge) i.next();
- int yindex = (int) ((int) Math.ceil(edge.y0) - (int) Math.ceil(icMinY));
+ int yindex = (int) Math.ceil(edge.y0) - (int) Math.ceil(icMinY);
if (edgeTable[yindex] == null) // Create bucket when needed.
edgeTable[yindex] = new ArrayList();
edgeTable[yindex].add(edge); // Add edge to the bucket of its line.
@@ -1767,7 +1840,8 @@ public abstract class AbstractGraphics2D
}
/**
- * Paints a scanline between x0 and x1.
+ * Paints a scanline between x0 and x1. Override this when your backend
+ * can efficiently draw/fill horizontal lines.
*
* @param x0 the left offset
* @param x1 the right offset
@@ -1973,8 +2047,7 @@ public abstract class AbstractGraphics2D
// Render full scanline.
//System.err.println("scanline: " + y);
if (! emptyScanline)
- fillScanlineAA(alpha, leftX, (int) y, rightX - leftX, pCtx,
- (int) minX);
+ fillScanlineAA(alpha, leftX, y, rightX - leftX, pCtx, (int) minX);
}
pCtx.dispose();
@@ -1987,7 +2060,7 @@ public abstract class AbstractGraphics2D
*
* @param alpha the alpha values in the scanline
* @param x0 the beginning of the scanline
- * @param y the y coordinate of the line
+ * @param yy the y coordinate of the line
*/
private void fillScanlineAA(int[] alpha, int x0, int yy, int numPixels,
PaintContext pCtx, int offs)
@@ -1998,7 +2071,6 @@ public abstract class AbstractGraphics2D
Raster paintRaster = pCtx.getRaster(x0, yy, numPixels, 1);
//System.err.println("paintColorModel: " + pCtx.getColorModel());
WritableRaster aaRaster = paintRaster.createCompatibleWritableRaster();
- int numBands = paintRaster.getNumBands();
ColorModel cm = pCtx.getColorModel();
double lastAlpha = 0.;
int lastAlphaInt = 0;
@@ -2157,10 +2229,10 @@ public abstract class AbstractGraphics2D
private static Rectangle computeIntersection(int x, int y, int w, int h,
Rectangle rect)
{
- int x2 = (int) rect.x;
- int y2 = (int) rect.y;
- int w2 = (int) rect.width;
- int h2 = (int) rect.height;
+ int x2 = rect.x;
+ int y2 = rect.y;
+ int w2 = rect.width;
+ int h2 = rect.height;
int dx = (x > x2) ? x : x2;
int dy = (y > y2) ? y : y2;
@@ -2267,4 +2339,20 @@ public abstract class AbstractGraphics2D
deviceBounds.setRect(minX, minY, maxX - minX, maxY - minY);
return segs;
}
+
+ /**
+ * Returns the ShapeCache for the calling thread.
+ *
+ * @return the ShapeCache for the calling thread
+ */
+ private ShapeCache getShapeCache()
+ {
+ ShapeCache sc = (ShapeCache) shapeCache.get();
+ if (sc == null)
+ {
+ sc = new ShapeCache();
+ shapeCache.set(sc);
+ }
+ return sc;
+ }
}