src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 20,37 ****
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
package sun.java2d.pipe;
import java.awt.BasicStroke;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
- import java.awt.geom.PathIterator;
import sun.awt.SunHints;
import sun.java2d.SunGraphics2D;
/**
* This class is used to convert raw geometry into 8-bit alpha tiles
--- 20,35 ----
*** 43,52 ****
--- 41,59 ----
public class AAShapePipe
implements ShapeDrawPipe, ParallelogramPipe
{
static RenderingEngine renderengine = RenderingEngine.getInstance();
+ // Per-thread TileState (~1K very small so do not use any Weak Reference)
+ private static final ThreadLocal<TileState> tileStateThreadLocal =
+ new ThreadLocal<TileState>() {
+ @Override
+ protected TileState initialValue() {
+ return new TileState();
+ }
+ };
+
CompositePipe outpipe;
public AAShapePipe(CompositePipe pipe) {
outpipe = pipe;
}
*** 66,107 ****
public void fill(SunGraphics2D sg, Shape s) {
renderPath(sg, s, null);
}
- private static Rectangle2D computeBBox(double ux1, double uy1,
- double ux2, double uy2)
- {
- if ((ux2 -= ux1) < 0) {
- ux1 += ux2;
- ux2 = -ux2;
- }
- if ((uy2 -= uy1) < 0) {
- uy1 += uy2;
- uy2 = -uy2;
- }
- return new Rectangle2D.Double(ux1, uy1, ux2, uy2);
- }
-
public void fillParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
double x, double y,
double dx1, double dy1,
double dx2, double dy2)
{
Region clip = sg.getCompClip();
! int abox[] = new int[4];
AATileGenerator aatg =
renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,
clip, abox);
if (aatg == null) {
// Nothing to render
return;
}
! renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
}
public void drawParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
--- 73,102 ----
public void fill(SunGraphics2D sg, Shape s) {
renderPath(sg, s, null);
}
public void fillParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
double x, double y,
double dx1, double dy1,
double dx2, double dy2)
{
Region clip = sg.getCompClip();
! final TileState ts = tileStateThreadLocal.get();
! final int[] abox = ts.abox;
!
AATileGenerator aatg =
renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,
clip, abox);
if (aatg == null) {
// Nothing to render
return;
}
! renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts);
}
public void drawParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
*** 109,188 ****
double dx1, double dy1,
double dx2, double dy2,
double lw1, double lw2)
{
Region clip = sg.getCompClip();
! int abox[] = new int[4];
AATileGenerator aatg =
renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2,
clip, abox);
if (aatg == null) {
// Nothing to render
return;
}
// Note that bbox is of the original shape, not the wide path.
// This is appropriate for handing to Paint methods...
! renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
! }
!
! private static byte[] theTile;
!
! private static synchronized byte[] getAlphaTile(int len) {
! byte[] t = theTile;
! if (t == null || t.length < len) {
! t = new byte[len];
! } else {
! theTile = null;
! }
! return t;
! }
!
! private static synchronized void dropAlphaTile(byte[] t) {
! theTile = t;
}
public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) {
boolean adjust = (bs != null &&
sg.strokeHint != SunHints.INTVAL_STROKE_PURE);
boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED);
Region clip = sg.getCompClip();
! int abox[] = new int[4];
AATileGenerator aatg =
renderengine.getAATileGenerator(s, sg.transform, clip,
bs, thin, adjust, abox);
if (aatg == null) {
// Nothing to render
return;
}
! renderTiles(sg, s, aatg, abox);
}
public void renderTiles(SunGraphics2D sg, Shape s,
! AATileGenerator aatg, int abox[])
{
Object context = null;
- byte alpha[] = null;
try {
context = outpipe.startSequence(sg, s,
! new Rectangle(abox[0], abox[1],
! abox[2] - abox[0],
! abox[3] - abox[1]),
abox);
! int tw = aatg.getTileWidth();
! int th = aatg.getTileHeight();
! alpha = getAlphaTile(tw * th);
byte[] atile;
for (int y = abox[1]; y < abox[3]; y += th) {
for (int x = abox[0]; x < abox[2]; x += tw) {
int w = Math.min(tw, abox[2] - x);
- int h = Math.min(th, abox[3] - y);
int a = aatg.getTypicalAlpha();
if (a == 0x00 ||
outpipe.needTile(context, x, y, w, h) == false)
{
--- 104,170 ----
double dx1, double dy1,
double dx2, double dy2,
double lw1, double lw2)
{
Region clip = sg.getCompClip();
! final TileState ts = tileStateThreadLocal.get();
! final int[] abox = ts.abox;
!
AATileGenerator aatg =
renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2,
clip, abox);
if (aatg == null) {
// Nothing to render
return;
}
// Note that bbox is of the original shape, not the wide path.
// This is appropriate for handing to Paint methods...
! renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts);
}
public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) {
boolean adjust = (bs != null &&
sg.strokeHint != SunHints.INTVAL_STROKE_PURE);
boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED);
Region clip = sg.getCompClip();
! final TileState ts = tileStateThreadLocal.get();
! final int[] abox = ts.abox;
!
AATileGenerator aatg =
renderengine.getAATileGenerator(s, sg.transform, clip,
bs, thin, adjust, abox);
if (aatg == null) {
// Nothing to render
return;
}
! renderTiles(sg, s, aatg, abox, ts);
}
public void renderTiles(SunGraphics2D sg, Shape s,
! AATileGenerator aatg, int abox[], TileState ts)
{
Object context = null;
try {
context = outpipe.startSequence(sg, s,
! ts.computeDevBox(abox),
abox);
! final int tw = aatg.getTileWidth();
! final int th = aatg.getTileHeight();
+ // get tile from thread local storage:
+ final byte[] alpha = ts.getAlphaTile(tw * th);
byte[] atile;
for (int y = abox[1]; y < abox[3]; y += th) {
+ int h = Math.min(th, abox[3] - y);
+
for (int x = abox[0]; x < abox[2]; x += tw) {
int w = Math.min(tw, abox[2] - x);
int a = aatg.getTypicalAlpha();
if (a == 0x00 ||
outpipe.needTile(context, x, y, w, h) == false)
{
*** 205,215 ****
} finally {
aatg.dispose();
if (context != null) {
outpipe.endSequence(context);
}
- if (alpha != null) {
- dropAlphaTile(alpha);
}
}
}
}
--- 187,244 ----
} finally {
aatg.dispose();
if (context != null) {
outpipe.endSequence(context);
}
}
}
+
+ // Tile state used by AAShapePipe
+ static final class TileState {
+ // cached tile (32 x 32 tile by default)
+ private byte[] theTile = new byte[32 * 32];
+ // dirty aabox array
+ final int[] abox = new int[4];
+ // dirty bbox rectangle
+ private final Rectangle dev = new Rectangle();
+ // dirty bbox rectangle2D.Double
+ private final Rectangle2D.Double bbox2D = new Rectangle2D.Double();
+
+ byte[] getAlphaTile(int len) {
+ byte[] t = theTile;
+ if (t.length < len) {
+ // create a larger tile and may free current theTile (too small)
+ theTile = t = new byte[len];
+ }
+ return t;
+ }
+
+ Rectangle computeDevBox(final int[] abox) {
+ final Rectangle box = this.dev;
+ box.x = abox[0];
+ box.y = abox[1];
+ box.width = abox[2] - abox[0];
+ box.height = abox[3] - abox[1];
+ return box;
}
+
+ Rectangle2D computeBBox(double ux1, double uy1,
+ double ux2, double uy2)
+ {
+ if ((ux2 -= ux1) < 0.0) {
+ ux1 += ux2;
+ ux2 = -ux2;
+ }
+ if ((uy2 -= uy1) < 0.0) {
+ uy1 += uy2;
+ uy2 = -uy2;
+ }
+ final Rectangle2D.Double box = this.bbox2D;
+ box.x = ux1;
+ box.y = uy1;
+ box.width = ux2;
+ box.height = uy2;
+ return box;
+ }
+ }
+
}