feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
261
jdkSrc/jdk8/sun/java2d/pipe/AAShapePipe.java
Normal file
261
jdkSrc/jdk8/sun/java2d/pipe/AAShapePipe.java
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2016, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.util.concurrent.ConcurrentLinkedQueue;
|
||||
import sun.awt.SunHints;
|
||||
import sun.java2d.ReentrantContext;
|
||||
import sun.java2d.ReentrantContextProvider;
|
||||
import sun.java2d.ReentrantContextProviderTL;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This class is used to convert raw geometry into 8-bit alpha tiles
|
||||
* using an AATileGenerator for application by the next stage of
|
||||
* the pipeline.
|
||||
* This class sets up the Generator and computes the alpha tiles
|
||||
* and then passes them on to a CompositePipe object for painting.
|
||||
*/
|
||||
public final class AAShapePipe
|
||||
implements ShapeDrawPipe, ParallelogramPipe
|
||||
{
|
||||
static final RenderingEngine renderengine = RenderingEngine.getInstance();
|
||||
|
||||
// Per-thread TileState (~1K very small so do not use any Weak Reference)
|
||||
private static final ReentrantContextProvider<TileState> tileStateProvider =
|
||||
new ReentrantContextProviderTL<TileState>(
|
||||
ReentrantContextProvider.REF_HARD)
|
||||
{
|
||||
@Override
|
||||
protected TileState newContext() {
|
||||
return new TileState();
|
||||
}
|
||||
};
|
||||
|
||||
final CompositePipe outpipe;
|
||||
|
||||
public AAShapePipe(CompositePipe pipe) {
|
||||
outpipe = pipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(SunGraphics2D sg, Shape s) {
|
||||
final BasicStroke bs;
|
||||
|
||||
if (sg.stroke instanceof BasicStroke) {
|
||||
bs = (BasicStroke) sg.stroke;
|
||||
} else {
|
||||
s = sg.stroke.createStrokedShape(s);
|
||||
bs = null;
|
||||
}
|
||||
|
||||
renderPath(sg, s, bs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill(SunGraphics2D sg, Shape s) {
|
||||
renderPath(sg, s, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
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)
|
||||
{
|
||||
final TileState ts = tileStateProvider.acquire();
|
||||
try {
|
||||
final int[] abox = ts.abox;
|
||||
|
||||
final AATileGenerator aatg =
|
||||
renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,
|
||||
sg.getCompClip(), abox);
|
||||
if (aatg != null) {
|
||||
renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2),
|
||||
aatg, abox, ts);
|
||||
}
|
||||
} finally {
|
||||
tileStateProvider.release(ts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawParallelogram(SunGraphics2D sg,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
final TileState ts = tileStateProvider.acquire();
|
||||
try {
|
||||
final int[] abox = ts.abox;
|
||||
|
||||
final AATileGenerator aatg =
|
||||
renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1,
|
||||
lw2, sg.getCompClip(), abox);
|
||||
if (aatg != null) {
|
||||
// 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);
|
||||
}
|
||||
} finally {
|
||||
tileStateProvider.release(ts);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) {
|
||||
final boolean adjust = (bs != null &&
|
||||
sg.strokeHint != SunHints.INTVAL_STROKE_PURE);
|
||||
final boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED);
|
||||
|
||||
final TileState ts = tileStateProvider.acquire();
|
||||
try {
|
||||
final int[] abox = ts.abox;
|
||||
|
||||
final AATileGenerator aatg =
|
||||
renderengine.getAATileGenerator(s, sg.transform, sg.getCompClip(),
|
||||
bs, thin, adjust, abox);
|
||||
if (aatg != null) {
|
||||
renderTiles(sg, s, aatg, abox, ts);
|
||||
}
|
||||
} finally {
|
||||
tileStateProvider.release(ts);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderTiles(SunGraphics2D sg, Shape s,
|
||||
final AATileGenerator aatg,
|
||||
final int[] abox, final TileState ts)
|
||||
{
|
||||
Object context = null;
|
||||
try {
|
||||
// reentrance: outpipe may also use AAShapePipe:
|
||||
context = outpipe.startSequence(sg, s,
|
||||
ts.computeDevBox(abox),
|
||||
abox);
|
||||
|
||||
// copy of int[] abox as local variables for performance:
|
||||
final int x0 = abox[0];
|
||||
final int y0 = abox[1];
|
||||
final int x1 = abox[2];
|
||||
final int y1 = abox[3];
|
||||
|
||||
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 = y0; y < y1; y += th) {
|
||||
final int h = Math.min(th, y1 - y);
|
||||
|
||||
for (int x = x0; x < x1; x += tw) {
|
||||
final int w = Math.min(tw, x1 - x);
|
||||
|
||||
final int a = aatg.getTypicalAlpha();
|
||||
|
||||
if (a == 0x00 || !outpipe.needTile(context, x, y, w, h)) {
|
||||
aatg.nextTile();
|
||||
outpipe.skipTile(context, x, y);
|
||||
continue;
|
||||
}
|
||||
if (a == 0xff) {
|
||||
atile = null;
|
||||
aatg.nextTile();
|
||||
} else {
|
||||
atile = alpha;
|
||||
aatg.getAlpha(alpha, 0, tw);
|
||||
}
|
||||
|
||||
outpipe.renderPathTile(context, atile, 0, tw, x, y, w, h);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
aatg.dispose();
|
||||
if (context != null) {
|
||||
outpipe.endSequence(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tile state used by AAShapePipe
|
||||
static final class TileState extends ReentrantContext {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
45
jdkSrc/jdk8/sun/java2d/pipe/AATextRenderer.java
Normal file
45
jdkSrc/jdk8/sun/java2d/pipe/AATextRenderer.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2005, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.font.GlyphVector;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.font.GlyphList;
|
||||
|
||||
/**
|
||||
* A delegate pipe of SG2D for drawing anti-aliased text with
|
||||
* a solid source colour to an opaque destination.
|
||||
*/
|
||||
|
||||
public class AATextRenderer extends GlyphListLoopPipe
|
||||
implements LoopBasedPipe
|
||||
{
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
|
||||
sg2d.loops.drawGlyphListAALoop.DrawGlyphListAA(sg2d, sg2d.surfaceData,
|
||||
gl);
|
||||
}
|
||||
|
||||
}
|
||||
111
jdkSrc/jdk8/sun/java2d/pipe/AATileGenerator.java
Normal file
111
jdkSrc/jdk8/sun/java2d/pipe/AATileGenerator.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The API for an object that generates alpha coverage tiles for a given
|
||||
* path.
|
||||
* The {@link RenderingEngine} will be consulted as a factory to return
|
||||
* one of these objects for a given Shape and a given set of rendering
|
||||
* attributes.
|
||||
* This object will iterate through the bounds of the rendering primitive
|
||||
* and return tiles of a constant size as specified by the getTileWidth()
|
||||
* and getTileHeight() parameters.
|
||||
* The iteration order of the tiles will be as specified by the pseudo-code:
|
||||
* <pre>
|
||||
* int bbox[] = {left, top, right, bottom};
|
||||
* AATileGenerator aatg = renderengine.getAATileGenerator(..., bbox);
|
||||
* int tw = aatg.getTileWidth();
|
||||
* int th = aatg.getTileHeight();
|
||||
* byte tile[] = new byte[tw * th];
|
||||
* for (y = top; y < bottom; y += th) {
|
||||
* for (x = left; x < right; x += tw) {
|
||||
* int a = aatg.getTypicalAlpha();
|
||||
* int w = Math.min(tw, right-x);
|
||||
* int h = Math.min(th, bottom-y);
|
||||
* if (a == 0x00) {
|
||||
* // can skip this tile...
|
||||
* aatg.nextTile();
|
||||
* } else if (a == 0xff) {
|
||||
* // can treat this tile like a fillRect
|
||||
* aatg.nextTile();
|
||||
* doFill(x, y, w, h);
|
||||
* } else {
|
||||
* aatg.getAlpha(tile, 0, tw);
|
||||
* handleAlpha(tile, x, y, w, h);
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* aatg.dispose();
|
||||
* </pre>
|
||||
* The bounding box for the iteration will be returned by the
|
||||
* {@code RenderingEngine} via an argument to the getAATileGenerator() method.
|
||||
*/
|
||||
public interface AATileGenerator {
|
||||
/**
|
||||
* Gets the width of the tiles that the generator batches output into.
|
||||
* @return the width of the standard alpha tile
|
||||
*/
|
||||
public int getTileWidth();
|
||||
|
||||
/**
|
||||
* Gets the height of the tiles that the generator batches output into.
|
||||
* @return the height of the standard alpha tile
|
||||
*/
|
||||
public int getTileHeight();
|
||||
|
||||
/**
|
||||
* Gets the typical alpha value that will characterize the current
|
||||
* tile.
|
||||
* The answer may be 0x00 to indicate that the current tile has
|
||||
* no coverage in any of its pixels, or it may be 0xff to indicate
|
||||
* that the current tile is completely covered by the path, or any
|
||||
* other value to indicate non-trivial coverage cases.
|
||||
* @return 0x00 for no coverage, 0xff for total coverage, or any other
|
||||
* value for partial coverage of the tile
|
||||
*/
|
||||
public int getTypicalAlpha();
|
||||
|
||||
/**
|
||||
* Skips the current tile and moves on to the next tile.
|
||||
* Either this method, or the getAlpha() method should be called
|
||||
* once per tile, but not both.
|
||||
*/
|
||||
public void nextTile();
|
||||
|
||||
/**
|
||||
* Gets the alpha coverage values for the current tile.
|
||||
* Either this method, or the nextTile() method should be called
|
||||
* once per tile, but not both.
|
||||
*/
|
||||
public void getAlpha(byte tile[], int offset, int rowstride);
|
||||
|
||||
/**
|
||||
* Disposes this tile generator.
|
||||
* No further calls will be made on this instance.
|
||||
*/
|
||||
public void dispose();
|
||||
}
|
||||
90
jdkSrc/jdk8/sun/java2d/pipe/AlphaColorPipe.java
Normal file
90
jdkSrc/jdk8/sun/java2d/pipe/AlphaColorPipe.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This class implements a CompositePipe that renders path alpha tiles
|
||||
* into a destination that supports direct alpha compositing of a solid
|
||||
* color, according to one of the rules in the AlphaComposite class.
|
||||
*/
|
||||
public class AlphaColorPipe implements CompositePipe, ParallelogramPipe {
|
||||
public AlphaColorPipe() {
|
||||
}
|
||||
|
||||
public Object startSequence(SunGraphics2D sg, Shape s, Rectangle dev,
|
||||
int[] abox) {
|
||||
return sg;
|
||||
}
|
||||
|
||||
public boolean needTile(Object context, int x, int y, int w, int h) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void renderPathTile(Object context,
|
||||
byte[] atile, int offset, int tilesize,
|
||||
int x, int y, int w, int h) {
|
||||
SunGraphics2D sg = (SunGraphics2D) context;
|
||||
|
||||
sg.alphafill.MaskFill(sg, sg.getSurfaceData(), sg.composite,
|
||||
x, y, w, h,
|
||||
atile, offset, tilesize);
|
||||
}
|
||||
|
||||
public void skipTile(Object context, int x, int y) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void endSequence(Object context) {
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
sg.alphafill.FillAAPgram(sg, sg.getSurfaceData(), sg.composite,
|
||||
x, y, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
|
||||
public void drawParallelogram(SunGraphics2D sg,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
sg.alphafill.DrawAAPgram(sg, sg.getSurfaceData(), sg.composite,
|
||||
x, y, dx1, dy1, dx2, dy2, lw1, lw2);
|
||||
}
|
||||
}
|
||||
206
jdkSrc/jdk8/sun/java2d/pipe/AlphaPaintPipe.java
Normal file
206
jdkSrc/jdk8/sun/java2d/pipe/AlphaPaintPipe.java
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2002, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.lang.ref.WeakReference;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.PaintContext;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.image.BufferedImage;
|
||||
import sun.awt.image.BufImgSurfaceData;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.MaskBlit;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
|
||||
/**
|
||||
* This class implements a CompositePipe that renders path alpha tiles
|
||||
* into a destination according to the Composite attribute of a
|
||||
* SunGraphics2D.
|
||||
*/
|
||||
public class AlphaPaintPipe implements CompositePipe {
|
||||
static WeakReference cachedLastRaster;
|
||||
static WeakReference cachedLastColorModel;
|
||||
static WeakReference cachedLastData;
|
||||
|
||||
static class TileContext {
|
||||
SunGraphics2D sunG2D;
|
||||
PaintContext paintCtxt;
|
||||
ColorModel paintModel;
|
||||
WeakReference lastRaster;
|
||||
WeakReference lastData;
|
||||
MaskBlit lastMask;
|
||||
Blit lastBlit;
|
||||
SurfaceData dstData;
|
||||
|
||||
public TileContext(SunGraphics2D sg, PaintContext pc) {
|
||||
sunG2D = sg;
|
||||
paintCtxt = pc;
|
||||
paintModel = pc.getColorModel();
|
||||
dstData = sg.getSurfaceData();
|
||||
synchronized (AlphaPaintPipe.class) {
|
||||
if (cachedLastColorModel != null &&
|
||||
cachedLastColorModel.get() == paintModel)
|
||||
{
|
||||
this.lastRaster = cachedLastRaster;
|
||||
this.lastData = cachedLastData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object startSequence(SunGraphics2D sg, Shape s, Rectangle devR,
|
||||
int[] abox) {
|
||||
PaintContext paintContext =
|
||||
sg.paint.createContext(sg.getDeviceColorModel(),
|
||||
devR,
|
||||
s.getBounds2D(),
|
||||
sg.cloneTransform(),
|
||||
sg.getRenderingHints());
|
||||
return new TileContext(sg, paintContext);
|
||||
}
|
||||
|
||||
public boolean needTile(Object context, int x, int y, int w, int h) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final int TILE_SIZE = 32;
|
||||
|
||||
public void renderPathTile(Object ctx,
|
||||
byte[] atile, int offset, int tilesize,
|
||||
int x, int y, int w, int h) {
|
||||
TileContext context = (TileContext) ctx;
|
||||
PaintContext paintCtxt = context.paintCtxt;
|
||||
SunGraphics2D sg = context.sunG2D;
|
||||
SurfaceData dstData = context.dstData;
|
||||
SurfaceData srcData = null;
|
||||
Raster lastRas = null;
|
||||
if (context.lastData != null && context.lastRaster != null) {
|
||||
srcData = (SurfaceData) context.lastData.get();
|
||||
lastRas = (Raster) context.lastRaster.get();
|
||||
if (srcData == null || lastRas == null) {
|
||||
srcData = null;
|
||||
lastRas = null;
|
||||
}
|
||||
}
|
||||
ColorModel paintModel = context.paintModel;
|
||||
|
||||
for (int rely = 0; rely < h; rely += TILE_SIZE) {
|
||||
int ty = y + rely;
|
||||
int th = Math.min(h-rely, TILE_SIZE);
|
||||
for (int relx = 0; relx < w; relx += TILE_SIZE) {
|
||||
int tx = x + relx;
|
||||
int tw = Math.min(w-relx, TILE_SIZE);
|
||||
|
||||
Raster srcRaster = paintCtxt.getRaster(tx, ty, tw, th);
|
||||
if ((srcRaster.getMinX() != 0) || (srcRaster.getMinY() != 0)) {
|
||||
srcRaster = srcRaster.createTranslatedChild(0, 0);
|
||||
}
|
||||
if (lastRas != srcRaster) {
|
||||
lastRas = srcRaster;
|
||||
context.lastRaster = new WeakReference(lastRas);
|
||||
// REMIND: This will fail for a non-Writable raster!
|
||||
BufferedImage bImg =
|
||||
new BufferedImage(paintModel,
|
||||
(WritableRaster) srcRaster,
|
||||
paintModel.isAlphaPremultiplied(),
|
||||
null);
|
||||
srcData = BufImgSurfaceData.createData(bImg);
|
||||
context.lastData = new WeakReference(srcData);
|
||||
context.lastMask = null;
|
||||
context.lastBlit = null;
|
||||
}
|
||||
|
||||
if (atile == null) {
|
||||
if (context.lastBlit == null) {
|
||||
CompositeType comptype = sg.imageComp;
|
||||
if (CompositeType.SrcOverNoEa.equals(comptype) &&
|
||||
paintModel.getTransparency() == Transparency.OPAQUE)
|
||||
{
|
||||
comptype = CompositeType.SrcNoEa;
|
||||
}
|
||||
context.lastBlit =
|
||||
Blit.getFromCache(srcData.getSurfaceType(),
|
||||
comptype,
|
||||
dstData.getSurfaceType());
|
||||
}
|
||||
context.lastBlit.Blit(srcData, dstData,
|
||||
sg.composite, null,
|
||||
0, 0, tx, ty, tw, th);
|
||||
} else {
|
||||
if (context.lastMask == null) {
|
||||
CompositeType comptype = sg.imageComp;
|
||||
if (CompositeType.SrcOverNoEa.equals(comptype) &&
|
||||
paintModel.getTransparency() == Transparency.OPAQUE)
|
||||
{
|
||||
comptype = CompositeType.SrcNoEa;
|
||||
}
|
||||
context.lastMask =
|
||||
MaskBlit.getFromCache(srcData.getSurfaceType(),
|
||||
comptype,
|
||||
dstData.getSurfaceType());
|
||||
}
|
||||
|
||||
int toff = offset + rely * tilesize + relx;
|
||||
context.lastMask.MaskBlit(srcData, dstData,
|
||||
sg.composite, null,
|
||||
0, 0, tx, ty, tw, th,
|
||||
atile, toff, tilesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void skipTile(Object context, int x, int y) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void endSequence(Object ctx) {
|
||||
TileContext context = (TileContext) ctx;
|
||||
if (context.paintCtxt != null) {
|
||||
context.paintCtxt.dispose();
|
||||
}
|
||||
synchronized (AlphaPaintPipe.class) {
|
||||
if (context.lastData != null) {
|
||||
cachedLastRaster = context.lastRaster;
|
||||
if (cachedLastColorModel == null ||
|
||||
cachedLastColorModel.get() != context.paintModel)
|
||||
{
|
||||
// Avoid creating new WeakReference if possible
|
||||
cachedLastColorModel =
|
||||
new WeakReference(context.paintModel);
|
||||
}
|
||||
cachedLastData = context.lastData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
393
jdkSrc/jdk8/sun/java2d/pipe/BufferedBufImgOps.java
Normal file
393
jdkSrc/jdk8/sun/java2d/pipe/BufferedBufImgOps.java
Normal file
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.color.ColorSpace;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ByteLookupTable;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.IndexColorModel;
|
||||
import java.awt.image.Kernel;
|
||||
import java.awt.image.LookupOp;
|
||||
import java.awt.image.LookupTable;
|
||||
import java.awt.image.RescaleOp;
|
||||
import java.awt.image.ShortLookupTable;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
public class BufferedBufImgOps {
|
||||
|
||||
public static void enableBufImgOp(RenderQueue rq, SurfaceData srcData,
|
||||
BufferedImage srcImg,
|
||||
BufferedImageOp biop)
|
||||
{
|
||||
if (biop instanceof ConvolveOp) {
|
||||
enableConvolveOp(rq, srcData, (ConvolveOp)biop);
|
||||
} else if (biop instanceof RescaleOp) {
|
||||
enableRescaleOp(rq, srcData, srcImg, (RescaleOp)biop);
|
||||
} else if (biop instanceof LookupOp) {
|
||||
enableLookupOp(rq, srcData, srcImg, (LookupOp)biop);
|
||||
} else {
|
||||
throw new InternalError("Unknown BufferedImageOp");
|
||||
}
|
||||
}
|
||||
|
||||
public static void disableBufImgOp(RenderQueue rq, BufferedImageOp biop) {
|
||||
if (biop instanceof ConvolveOp) {
|
||||
disableConvolveOp(rq);
|
||||
} else if (biop instanceof RescaleOp) {
|
||||
disableRescaleOp(rq);
|
||||
} else if (biop instanceof LookupOp) {
|
||||
disableLookupOp(rq);
|
||||
} else {
|
||||
throw new InternalError("Unknown BufferedImageOp");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************** ConvolveOp support ****************************/
|
||||
|
||||
public static boolean isConvolveOpValid(ConvolveOp cop) {
|
||||
Kernel kernel = cop.getKernel();
|
||||
int kw = kernel.getWidth();
|
||||
int kh = kernel.getHeight();
|
||||
// REMIND: we currently can only handle 3x3 and 5x5 kernels,
|
||||
// but hopefully this is just a temporary restriction;
|
||||
// see native shader comments for more details
|
||||
if (!(kw == 3 && kh == 3) && !(kw == 5 && kh == 5)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void enableConvolveOp(RenderQueue rq,
|
||||
SurfaceData srcData,
|
||||
ConvolveOp cop)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
boolean edgeZero =
|
||||
cop.getEdgeCondition() == ConvolveOp.EDGE_ZERO_FILL;
|
||||
Kernel kernel = cop.getKernel();
|
||||
int kernelWidth = kernel.getWidth();
|
||||
int kernelHeight = kernel.getHeight();
|
||||
int kernelSize = kernelWidth * kernelHeight;
|
||||
int sizeofFloat = 4;
|
||||
int totalBytesRequired = 4 + 8 + 12 + (kernelSize * sizeofFloat);
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(totalBytesRequired, 4);
|
||||
buf.putInt(ENABLE_CONVOLVE_OP);
|
||||
buf.putLong(srcData.getNativeOps());
|
||||
buf.putInt(edgeZero ? 1 : 0);
|
||||
buf.putInt(kernelWidth);
|
||||
buf.putInt(kernelHeight);
|
||||
buf.put(kernel.getKernelData(null));
|
||||
}
|
||||
|
||||
private static void disableConvolveOp(RenderQueue rq) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(DISABLE_CONVOLVE_OP);
|
||||
}
|
||||
|
||||
/**************************** RescaleOp support *****************************/
|
||||
|
||||
public static boolean isRescaleOpValid(RescaleOp rop,
|
||||
BufferedImage srcImg)
|
||||
{
|
||||
int numFactors = rop.getNumFactors();
|
||||
ColorModel srcCM = srcImg.getColorModel();
|
||||
|
||||
if (srcCM instanceof IndexColorModel) {
|
||||
throw new
|
||||
IllegalArgumentException("Rescaling cannot be "+
|
||||
"performed on an indexed image");
|
||||
}
|
||||
if (numFactors != 1 &&
|
||||
numFactors != srcCM.getNumColorComponents() &&
|
||||
numFactors != srcCM.getNumComponents())
|
||||
{
|
||||
throw new IllegalArgumentException("Number of scaling constants "+
|
||||
"does not equal the number of"+
|
||||
" of color or color/alpha "+
|
||||
" components");
|
||||
}
|
||||
|
||||
int csType = srcCM.getColorSpace().getType();
|
||||
if (csType != ColorSpace.TYPE_RGB &&
|
||||
csType != ColorSpace.TYPE_GRAY)
|
||||
{
|
||||
// Not prepared to deal with other color spaces
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numFactors == 2 || numFactors > 4) {
|
||||
// Not really prepared to handle this at the native level, so...
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void enableRescaleOp(RenderQueue rq,
|
||||
SurfaceData srcData,
|
||||
BufferedImage srcImg,
|
||||
RescaleOp rop)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
ColorModel srcCM = srcImg.getColorModel();
|
||||
boolean nonPremult =
|
||||
srcCM.hasAlpha() &&
|
||||
srcCM.isAlphaPremultiplied();
|
||||
|
||||
/*
|
||||
* Note: The user-provided scale factors and offsets are arranged
|
||||
* in R/G/B/A order, regardless of the raw data order of the
|
||||
* underlying Raster/DataBuffer. The source image data is ultimately
|
||||
* converted into RGBA data when uploaded to an OpenGL texture
|
||||
* (even for TYPE_GRAY), so the scale factors and offsets are already
|
||||
* in the order expected by the native OpenGL code.
|
||||
*
|
||||
* However, the offsets provided by the user are in a range dictated
|
||||
* by the size of each color/alpha band in the source image. For
|
||||
* example, for 8/8/8 data each offset is in the range [0,255],
|
||||
* for 5/5/5 data each offset is in the range [0,31], and so on.
|
||||
* The OpenGL shader only thinks in terms of [0,1], so below we need
|
||||
* to normalize the user-provided offset values into the range [0,1].
|
||||
*/
|
||||
int numFactors = rop.getNumFactors();
|
||||
float[] origScaleFactors = rop.getScaleFactors(null);
|
||||
float[] origOffsets = rop.getOffsets(null);
|
||||
|
||||
// To make things easier, we will always pass all four bands
|
||||
// down to native code...
|
||||
float[] normScaleFactors;
|
||||
float[] normOffsets;
|
||||
|
||||
if (numFactors == 1) {
|
||||
normScaleFactors = new float[4];
|
||||
normOffsets = new float[4];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
normScaleFactors[i] = origScaleFactors[0];
|
||||
normOffsets[i] = origOffsets[0];
|
||||
}
|
||||
// Leave alpha untouched...
|
||||
normScaleFactors[3] = 1.0f;
|
||||
normOffsets[3] = 0.0f;
|
||||
} else if (numFactors == 3) {
|
||||
normScaleFactors = new float[4];
|
||||
normOffsets = new float[4];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
normScaleFactors[i] = origScaleFactors[i];
|
||||
normOffsets[i] = origOffsets[i];
|
||||
}
|
||||
// Leave alpha untouched...
|
||||
normScaleFactors[3] = 1.0f;
|
||||
normOffsets[3] = 0.0f;
|
||||
} else { // (numFactors == 4)
|
||||
normScaleFactors = origScaleFactors;
|
||||
normOffsets = origOffsets;
|
||||
}
|
||||
|
||||
// The user-provided offsets are specified in the range
|
||||
// of each source color band, but the OpenGL shader only wants
|
||||
// to deal with data in the range [0,1], so we need to normalize
|
||||
// each offset value to the range [0,1] here.
|
||||
if (srcCM.getNumComponents() == 1) {
|
||||
// Gray data
|
||||
int nBits = srcCM.getComponentSize(0);
|
||||
int maxValue = (1 << nBits) - 1;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
normOffsets[i] /= maxValue;
|
||||
}
|
||||
} else {
|
||||
// RGB(A) data
|
||||
for (int i = 0; i < srcCM.getNumComponents(); i++) {
|
||||
int nBits = srcCM.getComponentSize(i);
|
||||
int maxValue = (1 << nBits) - 1;
|
||||
normOffsets[i] /= maxValue;
|
||||
}
|
||||
}
|
||||
|
||||
int sizeofFloat = 4;
|
||||
int totalBytesRequired = 4 + 8 + 4 + (4 * sizeofFloat * 2);
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(totalBytesRequired, 4);
|
||||
buf.putInt(ENABLE_RESCALE_OP);
|
||||
buf.putLong(srcData.getNativeOps());
|
||||
buf.putInt(nonPremult ? 1 : 0);
|
||||
buf.put(normScaleFactors);
|
||||
buf.put(normOffsets);
|
||||
}
|
||||
|
||||
private static void disableRescaleOp(RenderQueue rq) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(DISABLE_RESCALE_OP);
|
||||
}
|
||||
|
||||
/**************************** LookupOp support ******************************/
|
||||
|
||||
public static boolean isLookupOpValid(LookupOp lop,
|
||||
BufferedImage srcImg)
|
||||
{
|
||||
LookupTable table = lop.getTable();
|
||||
int numComps = table.getNumComponents();
|
||||
ColorModel srcCM = srcImg.getColorModel();
|
||||
|
||||
if (srcCM instanceof IndexColorModel) {
|
||||
throw new
|
||||
IllegalArgumentException("LookupOp cannot be "+
|
||||
"performed on an indexed image");
|
||||
}
|
||||
if (numComps != 1 &&
|
||||
numComps != srcCM.getNumComponents() &&
|
||||
numComps != srcCM.getNumColorComponents())
|
||||
{
|
||||
throw new IllegalArgumentException("Number of arrays in the "+
|
||||
" lookup table ("+
|
||||
numComps+
|
||||
") is not compatible with"+
|
||||
" the src image: "+srcImg);
|
||||
}
|
||||
|
||||
int csType = srcCM.getColorSpace().getType();
|
||||
if (csType != ColorSpace.TYPE_RGB &&
|
||||
csType != ColorSpace.TYPE_GRAY)
|
||||
{
|
||||
// Not prepared to deal with other color spaces
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numComps == 2 || numComps > 4) {
|
||||
// Not really prepared to handle this at the native level, so...
|
||||
return false;
|
||||
}
|
||||
|
||||
// The LookupTable spec says that "all arrays must be the
|
||||
// same size" but unfortunately the constructors do not
|
||||
// enforce that. Also, our native code only works with
|
||||
// arrays no larger than 256 elements, so check both of
|
||||
// these restrictions here.
|
||||
if (table instanceof ByteLookupTable) {
|
||||
byte[][] data = ((ByteLookupTable)table).getTable();
|
||||
for (int i = 1; i < data.length; i++) {
|
||||
if (data[i].length > 256 ||
|
||||
data[i].length != data[i-1].length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (table instanceof ShortLookupTable) {
|
||||
short[][] data = ((ShortLookupTable)table).getTable();
|
||||
for (int i = 1; i < data.length; i++) {
|
||||
if (data[i].length > 256 ||
|
||||
data[i].length != data[i-1].length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void enableLookupOp(RenderQueue rq,
|
||||
SurfaceData srcData,
|
||||
BufferedImage srcImg,
|
||||
LookupOp lop)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
boolean nonPremult =
|
||||
srcImg.getColorModel().hasAlpha() &&
|
||||
srcImg.isAlphaPremultiplied();
|
||||
|
||||
LookupTable table = lop.getTable();
|
||||
int numBands = table.getNumComponents();
|
||||
int offset = table.getOffset();
|
||||
int bandLength;
|
||||
int bytesPerElem;
|
||||
boolean shortData;
|
||||
|
||||
if (table instanceof ShortLookupTable) {
|
||||
short[][] data = ((ShortLookupTable)table).getTable();
|
||||
bandLength = data[0].length;
|
||||
bytesPerElem = 2;
|
||||
shortData = true;
|
||||
} else { // (table instanceof ByteLookupTable)
|
||||
byte[][] data = ((ByteLookupTable)table).getTable();
|
||||
bandLength = data[0].length;
|
||||
bytesPerElem = 1;
|
||||
shortData = false;
|
||||
}
|
||||
|
||||
// Adjust the LUT length so that it ends on a 4-byte boundary
|
||||
int totalLutBytes = numBands * bandLength * bytesPerElem;
|
||||
int paddedLutBytes = (totalLutBytes + 3) & (~3);
|
||||
int padding = paddedLutBytes - totalLutBytes;
|
||||
int totalBytesRequired = 4 + 8 + 20 + paddedLutBytes;
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(totalBytesRequired, 4);
|
||||
buf.putInt(ENABLE_LOOKUP_OP);
|
||||
buf.putLong(srcData.getNativeOps());
|
||||
buf.putInt(nonPremult ? 1 : 0);
|
||||
buf.putInt(shortData ? 1 : 0);
|
||||
buf.putInt(numBands);
|
||||
buf.putInt(bandLength);
|
||||
buf.putInt(offset);
|
||||
if (shortData) {
|
||||
short[][] data = ((ShortLookupTable)table).getTable();
|
||||
for (int i = 0; i < numBands; i++) {
|
||||
buf.put(data[i]);
|
||||
}
|
||||
} else {
|
||||
byte[][] data = ((ByteLookupTable)table).getTable();
|
||||
for (int i = 0; i < numBands; i++) {
|
||||
buf.put(data[i]);
|
||||
}
|
||||
}
|
||||
if (padding != 0) {
|
||||
buf.position(buf.position() + padding);
|
||||
}
|
||||
}
|
||||
|
||||
private static void disableLookupOp(RenderQueue rq) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(DISABLE_LOOKUP_OP);
|
||||
}
|
||||
}
|
||||
479
jdkSrc/jdk8/sun/java2d/pipe/BufferedContext.java
Normal file
479
jdkSrc/jdk8/sun/java2d/pipe/BufferedContext.java
Normal file
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2016, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Paint;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.XORComposite;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import static sun.java2d.pipe.BufferedRenderPipe.BYTES_PER_SPAN;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Base context class for managing state in a single-threaded rendering
|
||||
* environment. Each state-setting operation (e.g. SET_COLOR) is added to
|
||||
* the provided RenderQueue, which will be processed at a later time by a
|
||||
* single thread. Note that the RenderQueue lock must be acquired before
|
||||
* calling the validate() method (or any other method in this class). See
|
||||
* the RenderQueue class comments for a sample usage scenario.
|
||||
*
|
||||
* @see RenderQueue
|
||||
*/
|
||||
public abstract class BufferedContext {
|
||||
|
||||
/*
|
||||
* The following flags help the internals of validate() determine
|
||||
* the appropriate (meaning correct, or optimal) code path when
|
||||
* setting up the current context. The flags can be bitwise OR'd
|
||||
* together as needed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Indicates that no flags are needed; take all default code paths.
|
||||
*/
|
||||
@Native public static final int NO_CONTEXT_FLAGS = (0 << 0);
|
||||
/**
|
||||
* Indicates that the source surface (or color value, if it is a simple
|
||||
* rendering operation) is opaque (has an alpha value of 1.0). If this
|
||||
* flag is present, it allows us to disable blending in certain
|
||||
* situations in order to improve performance.
|
||||
*/
|
||||
@Native public static final int SRC_IS_OPAQUE = (1 << 0);
|
||||
/**
|
||||
* Indicates that the operation uses an alpha mask, which may determine
|
||||
* the code path that is used when setting up the current paint state.
|
||||
*/
|
||||
@Native public static final int USE_MASK = (1 << 1);
|
||||
|
||||
protected RenderQueue rq;
|
||||
protected RenderBuffer buf;
|
||||
|
||||
/**
|
||||
* This is a reference to the most recently validated BufferedContext. If
|
||||
* this value is null, it means that there is no current context. It is
|
||||
* provided here so that validate() only needs to do a quick reference
|
||||
* check to see if the BufferedContext passed to that method is the same
|
||||
* as the one we've cached here.
|
||||
*/
|
||||
protected static BufferedContext currentContext;
|
||||
|
||||
private Reference<AccelSurface> validSrcDataRef = new WeakReference<>(null);
|
||||
private Reference<AccelSurface> validDstDataRef = new WeakReference<>(null);
|
||||
private Reference<Region> validClipRef = new WeakReference<>(null);
|
||||
private Reference<Composite> validCompRef = new WeakReference<>(null);
|
||||
private Reference<Paint> validPaintRef = new WeakReference<>(null);
|
||||
// renamed from isValidatedPaintAColor as part of a work around for 6764257
|
||||
private boolean isValidatedPaintJustAColor;
|
||||
private int validatedRGB;
|
||||
private int validatedFlags;
|
||||
private boolean xformInUse;
|
||||
private AffineTransform transform;
|
||||
|
||||
protected BufferedContext(RenderQueue rq) {
|
||||
this.rq = rq;
|
||||
this.buf = rq.getBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the BufferedContextContext associated with the dst. surface
|
||||
* and validates the context using the given parameters. Most rendering
|
||||
* operations will call this method first in order to set the necessary
|
||||
* state before issuing rendering commands.
|
||||
*
|
||||
* Note: must be called while the RenderQueue lock is held.
|
||||
*
|
||||
* It's assumed that the type of surfaces has been checked by the Renderer
|
||||
*
|
||||
* @throws InvalidPipeException if either src or dest surface is not valid
|
||||
* or lost
|
||||
* @see RenderQueue#lock
|
||||
* @see RenderQueue#unlock
|
||||
*/
|
||||
public static void validateContext(AccelSurface srcData,
|
||||
AccelSurface dstData,
|
||||
Region clip, Composite comp,
|
||||
AffineTransform xform,
|
||||
Paint paint, SunGraphics2D sg2d,
|
||||
int flags)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
BufferedContext context = dstData.getContext();
|
||||
context.validate(srcData, dstData,
|
||||
clip, comp, xform, paint, sg2d, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the BufferedContextassociated with the surface
|
||||
* and disables all context state settings.
|
||||
*
|
||||
* Note: must be called while the RenderQueue lock is held.
|
||||
*
|
||||
* It's assumed that the type of surfaces has been checked by the Renderer
|
||||
*
|
||||
* @throws InvalidPipeException if the surface is not valid
|
||||
* or lost
|
||||
* @see RenderQueue#lock
|
||||
* @see RenderQueue#unlock
|
||||
*/
|
||||
public static void validateContext(AccelSurface surface) {
|
||||
// assert rt.lock.isHeldByCurrentThread();
|
||||
validateContext(surface, surface,
|
||||
null, null, null, null, null, NO_CONTEXT_FLAGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given parameters against the current state for this
|
||||
* context. If this context is not current, it will be made current
|
||||
* for the given source and destination surfaces, and the viewport will
|
||||
* be updated. Then each part of the context state (clip, composite,
|
||||
* etc.) is checked against the previous value. If the value has changed
|
||||
* since the last call to validate(), it will be updated accordingly.
|
||||
*
|
||||
* Note that the SunGraphics2D parameter is only used for the purposes
|
||||
* of validating a (non-null) Paint parameter. In all other cases it
|
||||
* is safe to pass a null SunGraphics2D and it will be ignored.
|
||||
*
|
||||
* Note: must be called while the RenderQueue lock is held.
|
||||
*
|
||||
* It's assumed that the type of surfaces has been checked by the Renderer
|
||||
*
|
||||
* @throws InvalidPipeException if either src or dest surface is not valid
|
||||
* or lost
|
||||
*/
|
||||
public void validate(AccelSurface srcData, AccelSurface dstData,
|
||||
Region clip, Composite comp,
|
||||
AffineTransform xform,
|
||||
Paint paint, SunGraphics2D sg2d, int flags)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
|
||||
boolean updateClip = false;
|
||||
boolean updatePaint = false;
|
||||
|
||||
if (!dstData.isValid() ||
|
||||
dstData.isSurfaceLost() || srcData.isSurfaceLost())
|
||||
{
|
||||
invalidateContext();
|
||||
throw new InvalidPipeException("bounds changed or surface lost");
|
||||
}
|
||||
|
||||
if (paint instanceof Color) {
|
||||
// REMIND: not 30-bit friendly
|
||||
int newRGB = ((Color)paint).getRGB();
|
||||
if (isValidatedPaintJustAColor) {
|
||||
if (newRGB != validatedRGB) {
|
||||
validatedRGB = newRGB;
|
||||
updatePaint = true;
|
||||
}
|
||||
} else {
|
||||
validatedRGB = newRGB;
|
||||
updatePaint = true;
|
||||
isValidatedPaintJustAColor = true;
|
||||
}
|
||||
} else if (validPaintRef.get() != paint) {
|
||||
updatePaint = true;
|
||||
// this should be set when we are switching from paint to color
|
||||
// in which case this condition will be true
|
||||
isValidatedPaintJustAColor = false;
|
||||
}
|
||||
|
||||
final AccelSurface validatedSrcData = validSrcDataRef.get();
|
||||
final AccelSurface validatedDstData = validDstDataRef.get();
|
||||
if ((currentContext != this) ||
|
||||
(srcData != validatedSrcData) ||
|
||||
(dstData != validatedDstData))
|
||||
{
|
||||
if (dstData != validatedDstData) {
|
||||
// the clip is dependent on the destination surface, so we
|
||||
// need to update it if we have a new destination surface
|
||||
updateClip = true;
|
||||
}
|
||||
|
||||
if (paint == null) {
|
||||
// make sure we update the color state (otherwise, it might
|
||||
// not be updated if this is the first time the context
|
||||
// is being validated)
|
||||
updatePaint = true;
|
||||
}
|
||||
|
||||
// update the current source and destination surfaces
|
||||
setSurfaces(srcData, dstData);
|
||||
|
||||
currentContext = this;
|
||||
validSrcDataRef = new WeakReference<>(srcData);
|
||||
validDstDataRef = new WeakReference<>(dstData);
|
||||
}
|
||||
|
||||
// validate clip
|
||||
final Region validatedClip = validClipRef.get();
|
||||
if ((clip != validatedClip) || updateClip) {
|
||||
if (clip != null) {
|
||||
if (updateClip ||
|
||||
validatedClip == null ||
|
||||
!(validatedClip.isRectangular() && clip.isRectangular()) ||
|
||||
((clip.getLoX() != validatedClip.getLoX() ||
|
||||
clip.getLoY() != validatedClip.getLoY() ||
|
||||
clip.getHiX() != validatedClip.getHiX() ||
|
||||
clip.getHiY() != validatedClip.getHiY())))
|
||||
{
|
||||
setClip(clip);
|
||||
}
|
||||
} else {
|
||||
resetClip();
|
||||
}
|
||||
validClipRef = new WeakReference<>(clip);
|
||||
}
|
||||
|
||||
// validate composite (note that a change in the context flags
|
||||
// may require us to update the composite state, even if the
|
||||
// composite has not changed)
|
||||
if ((comp != validCompRef.get()) || (flags != validatedFlags)) {
|
||||
if (comp != null) {
|
||||
setComposite(comp, flags);
|
||||
} else {
|
||||
resetComposite();
|
||||
}
|
||||
// the paint state is dependent on the composite state, so make
|
||||
// sure we update the color below
|
||||
updatePaint = true;
|
||||
validCompRef = new WeakReference<>(comp);
|
||||
validatedFlags = flags;
|
||||
}
|
||||
|
||||
// validate transform
|
||||
boolean txChanged = false;
|
||||
if (xform == null) {
|
||||
if (xformInUse) {
|
||||
resetTransform();
|
||||
xformInUse = false;
|
||||
txChanged = true;
|
||||
} else if (sg2d != null && !sg2d.transform.equals(transform)) {
|
||||
txChanged = true;
|
||||
}
|
||||
if (sg2d != null && txChanged) {
|
||||
transform = new AffineTransform(sg2d.transform);
|
||||
}
|
||||
} else {
|
||||
setTransform(xform);
|
||||
xformInUse = true;
|
||||
txChanged = true;
|
||||
}
|
||||
// non-Color paints may require paint revalidation
|
||||
if (!isValidatedPaintJustAColor && txChanged) {
|
||||
updatePaint = true;
|
||||
}
|
||||
|
||||
// validate paint
|
||||
if (updatePaint) {
|
||||
if (paint != null) {
|
||||
BufferedPaints.setPaint(rq, sg2d, paint, flags);
|
||||
} else {
|
||||
BufferedPaints.resetPaint(rq);
|
||||
}
|
||||
validPaintRef = new WeakReference<>(paint);
|
||||
}
|
||||
|
||||
// mark dstData dirty
|
||||
// REMIND: is this really needed now? we do it in SunGraphics2D..
|
||||
dstData.markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the surfaces associated with this context. This is
|
||||
* useful when the context is no longer needed, and we want to break
|
||||
* the chain caused by these surface references.
|
||||
*
|
||||
* Note: must be called while the RenderQueue lock is held.
|
||||
*
|
||||
* @see RenderQueue#lock
|
||||
* @see RenderQueue#unlock
|
||||
*/
|
||||
private void invalidateSurfaces() {
|
||||
validSrcDataRef.clear();
|
||||
validDstDataRef.clear();
|
||||
}
|
||||
|
||||
private void setSurfaces(AccelSurface srcData,
|
||||
AccelSurface dstData)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacityAndAlignment(20, 4);
|
||||
buf.putInt(SET_SURFACES);
|
||||
buf.putLong(srcData.getNativeOps());
|
||||
buf.putLong(dstData.getNativeOps());
|
||||
}
|
||||
|
||||
private void resetClip() {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(RESET_CLIP);
|
||||
}
|
||||
|
||||
private void setClip(Region clip) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
if (clip.isRectangular()) {
|
||||
rq.ensureCapacity(20);
|
||||
buf.putInt(SET_RECT_CLIP);
|
||||
buf.putInt(clip.getLoX()).putInt(clip.getLoY());
|
||||
buf.putInt(clip.getHiX()).putInt(clip.getHiY());
|
||||
} else {
|
||||
rq.ensureCapacity(28); // so that we have room for at least a span
|
||||
buf.putInt(BEGIN_SHAPE_CLIP);
|
||||
buf.putInt(SET_SHAPE_CLIP_SPANS);
|
||||
// include a placeholder for the span count
|
||||
int countIndex = buf.position();
|
||||
buf.putInt(0);
|
||||
int spanCount = 0;
|
||||
int remainingSpans = buf.remaining() / BYTES_PER_SPAN;
|
||||
int span[] = new int[4];
|
||||
SpanIterator si = clip.getSpanIterator();
|
||||
while (si.nextSpan(span)) {
|
||||
if (remainingSpans == 0) {
|
||||
buf.putInt(countIndex, spanCount);
|
||||
rq.flushNow();
|
||||
buf.putInt(SET_SHAPE_CLIP_SPANS);
|
||||
countIndex = buf.position();
|
||||
buf.putInt(0);
|
||||
spanCount = 0;
|
||||
remainingSpans = buf.remaining() / BYTES_PER_SPAN;
|
||||
}
|
||||
buf.putInt(span[0]); // x1
|
||||
buf.putInt(span[1]); // y1
|
||||
buf.putInt(span[2]); // x2
|
||||
buf.putInt(span[3]); // y2
|
||||
spanCount++;
|
||||
remainingSpans--;
|
||||
}
|
||||
buf.putInt(countIndex, spanCount);
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(END_SHAPE_CLIP);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetComposite() {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(RESET_COMPOSITE);
|
||||
}
|
||||
|
||||
private void setComposite(Composite comp, int flags) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
if (comp instanceof AlphaComposite) {
|
||||
AlphaComposite ac = (AlphaComposite)comp;
|
||||
rq.ensureCapacity(16);
|
||||
buf.putInt(SET_ALPHA_COMPOSITE);
|
||||
buf.putInt(ac.getRule());
|
||||
buf.putFloat(ac.getAlpha());
|
||||
buf.putInt(flags);
|
||||
} else if (comp instanceof XORComposite) {
|
||||
int xorPixel = ((XORComposite)comp).getXorPixel();
|
||||
rq.ensureCapacity(8);
|
||||
buf.putInt(SET_XOR_COMPOSITE);
|
||||
buf.putInt(xorPixel);
|
||||
} else {
|
||||
throw new InternalError("not yet implemented");
|
||||
}
|
||||
}
|
||||
|
||||
private void resetTransform() {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(RESET_TRANSFORM);
|
||||
}
|
||||
|
||||
private void setTransform(AffineTransform xform) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacityAndAlignment(52, 4);
|
||||
buf.putInt(SET_TRANSFORM);
|
||||
buf.putDouble(xform.getScaleX());
|
||||
buf.putDouble(xform.getShearY());
|
||||
buf.putDouble(xform.getShearX());
|
||||
buf.putDouble(xform.getScaleY());
|
||||
buf.putDouble(xform.getTranslateX());
|
||||
buf.putDouble(xform.getTranslateY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this context's surfaces and all attributes.
|
||||
*
|
||||
* Note: must be called while the RenderQueue lock is held.
|
||||
*
|
||||
* @see RenderQueue#lock
|
||||
* @see RenderQueue#unlock
|
||||
*/
|
||||
public void invalidateContext() {
|
||||
resetTransform();
|
||||
resetComposite();
|
||||
resetClip();
|
||||
BufferedPaints.resetPaint(rq);
|
||||
invalidateSurfaces();
|
||||
validCompRef.clear();
|
||||
validClipRef.clear();
|
||||
validPaintRef.clear();
|
||||
isValidatedPaintJustAColor = false;
|
||||
xformInUse = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a singleton {@code RenderQueue} object used by the rendering
|
||||
* pipeline.
|
||||
*
|
||||
* @return a render queue
|
||||
* @see RenderQueue
|
||||
*/
|
||||
public abstract RenderQueue getRenderQueue();
|
||||
|
||||
/**
|
||||
* Saves the the state of this context.
|
||||
* It may reset the current context.
|
||||
*
|
||||
* Note: must be called while the RenderQueue lock is held.
|
||||
*
|
||||
* @see RenderQueue#lock
|
||||
* @see RenderQueue#unlock
|
||||
*/
|
||||
public abstract void saveState();
|
||||
|
||||
/**
|
||||
* Restores the native state of this context.
|
||||
* It may reset the current context.
|
||||
*
|
||||
* Note: must be called while the RenderQueue lock is held.
|
||||
*
|
||||
* @see RenderQueue#lock
|
||||
* @see RenderQueue#unlock
|
||||
*/
|
||||
public abstract void restoreState();
|
||||
}
|
||||
163
jdkSrc/jdk8/sun/java2d/pipe/BufferedMaskBlit.java
Normal file
163
jdkSrc/jdk8/sun/java2d/pipe/BufferedMaskBlit.java
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.AlphaComposite;
|
||||
import java.awt.Composite;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.MaskBlit;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
/**
|
||||
* The MaskBlit operation is expressed as:
|
||||
* dst = ((src <MODE> dst) * pathA) + (dst * (1 - pathA))
|
||||
*
|
||||
* The OGL/D3D implementation of the MaskBlit operation differs from the above
|
||||
* equation because it is not possible to perform such a complex operation in
|
||||
* OpenGL/Direct3D (without the use of advanced techniques like fragment
|
||||
* shaders and multitexturing). Therefore, the BufferedMaskBlit operation
|
||||
* is expressed as:
|
||||
* dst = (src * pathA) <SrcOver> dst
|
||||
*
|
||||
* This simplified formula is only equivalent to the "true" MaskBlit equation
|
||||
* in the following situations:
|
||||
* - <MODE> is SrcOver
|
||||
* - <MODE> is Src, extra alpha == 1.0, and the source surface is opaque
|
||||
*
|
||||
* Therefore, we register BufferedMaskBlit primitives for only the SurfaceType
|
||||
* and CompositeType restrictions mentioned above. In addition for the Src
|
||||
* case, we must override the composite with a SrcOver (no extra alpha)
|
||||
* instance, so that we set up the OpenGL/Direct3D blending mode to match the
|
||||
* BufferedMaskBlit equation.
|
||||
*/
|
||||
public abstract class BufferedMaskBlit extends MaskBlit {
|
||||
|
||||
private static final int ST_INT_ARGB = 0;
|
||||
private static final int ST_INT_ARGB_PRE = 1;
|
||||
private static final int ST_INT_RGB = 2;
|
||||
private static final int ST_INT_BGR = 3;
|
||||
|
||||
private final RenderQueue rq;
|
||||
private final int srcTypeVal;
|
||||
private Blit blitop;
|
||||
|
||||
protected BufferedMaskBlit(RenderQueue rq,
|
||||
SurfaceType srcType,
|
||||
CompositeType compType,
|
||||
SurfaceType dstType)
|
||||
{
|
||||
super(srcType, compType, dstType);
|
||||
this.rq = rq;
|
||||
if (srcType == SurfaceType.IntArgb) {
|
||||
this.srcTypeVal = ST_INT_ARGB;
|
||||
} else if (srcType == SurfaceType.IntArgbPre) {
|
||||
this.srcTypeVal = ST_INT_ARGB_PRE;
|
||||
} else if (srcType == SurfaceType.IntRgb) {
|
||||
this.srcTypeVal = ST_INT_RGB;
|
||||
} else if (srcType == SurfaceType.IntBgr) {
|
||||
this.srcTypeVal = ST_INT_BGR;
|
||||
} else {
|
||||
throw new InternalError("unrecognized source surface type");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MaskBlit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int srcx, int srcy,
|
||||
int dstx, int dsty,
|
||||
int width, int height,
|
||||
byte[] mask, int maskoff, int maskscan)
|
||||
{
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask == null) {
|
||||
// no mask involved; delegate to regular blit loop
|
||||
if (blitop == null) {
|
||||
blitop = Blit.getFromCache(src.getSurfaceType(),
|
||||
CompositeType.AnyAlpha,
|
||||
this.getDestType());
|
||||
}
|
||||
blitop.Blit(src, dst,
|
||||
comp, clip,
|
||||
srcx, srcy, dstx, dsty,
|
||||
width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
AlphaComposite acomp = (AlphaComposite)comp;
|
||||
if (acomp.getRule() != AlphaComposite.SRC_OVER) {
|
||||
comp = AlphaComposite.SrcOver;
|
||||
}
|
||||
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(dst, comp, clip);
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
int totalBytesRequired = 20 + (width * height * 4);
|
||||
|
||||
/*
|
||||
* REMIND: we should fix this so that it works with tiles that
|
||||
* are larger than the entire buffer, but the native
|
||||
* OGL/D3DMaskBlit isn't even prepared for tiles larger
|
||||
* than 32x32 pixels, so there's no urgency here...
|
||||
*/
|
||||
rq.ensureCapacity(totalBytesRequired);
|
||||
|
||||
// enqueue parameters and tile pixels
|
||||
int newpos = enqueueTile(buf.getAddress(), buf.position(),
|
||||
src, src.getNativeOps(), srcTypeVal,
|
||||
mask, mask.length, maskoff, maskscan,
|
||||
srcx, srcy, dstx, dsty,
|
||||
width, height);
|
||||
|
||||
buf.position(newpos);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private native int enqueueTile(long buf, int bpos,
|
||||
SurfaceData srcData,
|
||||
long pSrcOps, int srcType,
|
||||
byte[] mask, int masklen,
|
||||
int maskoff, int maskscan,
|
||||
int srcx, int srcy, int dstx, int dsty,
|
||||
int width, int height);
|
||||
|
||||
/**
|
||||
* Validates the context state using the given destination surface
|
||||
* and composite/clip values.
|
||||
*/
|
||||
protected abstract void validateContext(SurfaceData dstData,
|
||||
Composite comp, Region clip);
|
||||
}
|
||||
153
jdkSrc/jdk8/sun/java2d/pipe/BufferedMaskFill.java
Normal file
153
jdkSrc/jdk8/sun/java2d/pipe/BufferedMaskFill.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.AlphaComposite;
|
||||
import java.awt.Composite;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.MaskFill;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
/**
|
||||
* The MaskFill operation is expressed as:
|
||||
* dst = ((src <MODE> dst) * pathA) + (dst * (1 - pathA))
|
||||
*
|
||||
* The OGL/D3D implementation of the MaskFill operation differs from the above
|
||||
* equation because it is not possible to perform such a complex operation in
|
||||
* OpenGL/Direct3D (without the use of advanced techniques like fragment
|
||||
* shaders and multitexturing). Therefore, the BufferedMaskFill operation
|
||||
* is expressed as:
|
||||
* dst = (src * pathA) <SrcOver> dst
|
||||
*
|
||||
* This simplified formula is only equivalent to the "true" MaskFill equation
|
||||
* in the following situations:
|
||||
* - <MODE> is SrcOver
|
||||
* - <MODE> is Src, extra alpha == 1.0, and the source paint is opaque
|
||||
*
|
||||
* Therefore, we register BufferedMaskFill primitives for only the SurfaceType
|
||||
* and CompositeType restrictions mentioned above. In addition, for the
|
||||
* SrcNoEa case we must override the incoming composite with a SrcOver (no
|
||||
* extra alpha) instance, so that we set up the OpenGL/Direct3D blending
|
||||
* mode to match the BufferedMaskFill equation.
|
||||
*/
|
||||
public abstract class BufferedMaskFill extends MaskFill {
|
||||
|
||||
protected final RenderQueue rq;
|
||||
|
||||
protected BufferedMaskFill(RenderQueue rq,
|
||||
SurfaceType srcType,
|
||||
CompositeType compType,
|
||||
SurfaceType dstType)
|
||||
{
|
||||
super(srcType, compType, dstType);
|
||||
this.rq = rq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MaskFill(SunGraphics2D sg2d, SurfaceData sData,
|
||||
Composite comp,
|
||||
final int x, final int y, final int w, final int h,
|
||||
final byte[] mask,
|
||||
final int maskoff, final int maskscan)
|
||||
{
|
||||
AlphaComposite acomp = (AlphaComposite)comp;
|
||||
if (acomp.getRule() != AlphaComposite.SRC_OVER) {
|
||||
comp = AlphaComposite.SrcOver;
|
||||
}
|
||||
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d, comp, BufferedContext.USE_MASK);
|
||||
|
||||
// we adjust the mask length so that the mask ends on a
|
||||
// 4-byte boundary
|
||||
int maskBytesRequired;
|
||||
if (mask != null) {
|
||||
// we adjust the mask length so that the mask ends on a
|
||||
// 4-byte boundary
|
||||
maskBytesRequired = (mask.length + 3) & (~3);
|
||||
} else {
|
||||
// mask not needed
|
||||
maskBytesRequired = 0;
|
||||
}
|
||||
int totalBytesRequired = 32 + maskBytesRequired;
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
if (totalBytesRequired <= buf.capacity()) {
|
||||
if (totalBytesRequired > buf.remaining()) {
|
||||
// process the queue first and then enqueue the mask
|
||||
rq.flushNow();
|
||||
}
|
||||
|
||||
buf.putInt(MASK_FILL);
|
||||
// enqueue parameters
|
||||
buf.putInt(x).putInt(y).putInt(w).putInt(h);
|
||||
buf.putInt(maskoff);
|
||||
buf.putInt(maskscan);
|
||||
buf.putInt(maskBytesRequired);
|
||||
if (mask != null) {
|
||||
// enqueue the mask
|
||||
int padding = maskBytesRequired - mask.length;
|
||||
buf.put(mask);
|
||||
if (padding != 0) {
|
||||
buf.position(buf.position() + padding);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// queue is too small to accommodate entire mask; perform
|
||||
// the operation directly on the queue flushing thread
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
maskFill(x, y, w, h,
|
||||
maskoff, maskscan, mask.length, mask);
|
||||
}
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called as a separate Runnable when the operation is too large to fit
|
||||
* on the RenderQueue. The OGL/D3D pipelines each have their own (small)
|
||||
* native implementation of this method.
|
||||
*/
|
||||
protected abstract void maskFill(int x, int y, int w, int h,
|
||||
int maskoff, int maskscan, int masklen,
|
||||
byte[] mask);
|
||||
|
||||
/**
|
||||
* Validates the state in the provided SunGraphics2D object and sets up
|
||||
* any special resources for this operation (e.g. enabling gradient
|
||||
* shading).
|
||||
*/
|
||||
protected abstract void validateContext(SunGraphics2D sg2d,
|
||||
Composite comp, int ctxflags);
|
||||
}
|
||||
101
jdkSrc/jdk8/sun/java2d/pipe/BufferedOpCodes.java
Normal file
101
jdkSrc/jdk8/sun/java2d/pipe/BufferedOpCodes.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.lang.annotation.Native;
|
||||
|
||||
public class BufferedOpCodes {
|
||||
// draw ops
|
||||
@Native public static final int DRAW_LINE = 10;
|
||||
@Native public static final int DRAW_RECT = 11;
|
||||
@Native public static final int DRAW_POLY = 12;
|
||||
@Native public static final int DRAW_PIXEL = 13;
|
||||
@Native public static final int DRAW_SCANLINES = 14;
|
||||
@Native public static final int DRAW_PARALLELOGRAM = 15;
|
||||
@Native public static final int DRAW_AAPARALLELOGRAM = 16;
|
||||
|
||||
// fill ops
|
||||
@Native public static final int FILL_RECT = 20;
|
||||
@Native public static final int FILL_SPANS = 21;
|
||||
@Native public static final int FILL_PARALLELOGRAM = 22;
|
||||
@Native public static final int FILL_AAPARALLELOGRAM = 23;
|
||||
|
||||
// copy-related ops
|
||||
@Native public static final int COPY_AREA = 30;
|
||||
@Native public static final int BLIT = 31;
|
||||
@Native public static final int MASK_FILL = 32;
|
||||
@Native public static final int MASK_BLIT = 33;
|
||||
@Native public static final int SURFACE_TO_SW_BLIT = 34;
|
||||
|
||||
// text-related ops
|
||||
@Native public static final int DRAW_GLYPH_LIST = 40;
|
||||
|
||||
// state-related ops
|
||||
@Native public static final int SET_RECT_CLIP = 51;
|
||||
@Native public static final int BEGIN_SHAPE_CLIP = 52;
|
||||
@Native public static final int SET_SHAPE_CLIP_SPANS = 53;
|
||||
@Native public static final int END_SHAPE_CLIP = 54;
|
||||
@Native public static final int RESET_CLIP = 55;
|
||||
@Native public static final int SET_ALPHA_COMPOSITE = 56;
|
||||
@Native public static final int SET_XOR_COMPOSITE = 57;
|
||||
@Native public static final int RESET_COMPOSITE = 58;
|
||||
@Native public static final int SET_TRANSFORM = 59;
|
||||
@Native public static final int RESET_TRANSFORM = 60;
|
||||
|
||||
// context-related ops
|
||||
@Native public static final int SET_SURFACES = 70;
|
||||
@Native public static final int SET_SCRATCH_SURFACE = 71;
|
||||
@Native public static final int FLUSH_SURFACE = 72;
|
||||
@Native public static final int DISPOSE_SURFACE = 73;
|
||||
@Native public static final int DISPOSE_CONFIG = 74;
|
||||
@Native public static final int INVALIDATE_CONTEXT = 75;
|
||||
@Native public static final int SYNC = 76;
|
||||
@Native public static final int RESTORE_DEVICES = 77;
|
||||
@Native public static final int SAVE_STATE = 78;
|
||||
@Native public static final int RESTORE_STATE = 79;
|
||||
|
||||
// multibuffering ops
|
||||
@Native public static final int SWAP_BUFFERS = 80;
|
||||
|
||||
// special no-op op code (mainly used for achieving 8-byte alignment)
|
||||
@Native public static final int NOOP = 90;
|
||||
|
||||
// paint-related ops
|
||||
@Native public static final int RESET_PAINT = 100;
|
||||
@Native public static final int SET_COLOR = 101;
|
||||
@Native public static final int SET_GRADIENT_PAINT = 102;
|
||||
@Native public static final int SET_LINEAR_GRADIENT_PAINT = 103;
|
||||
@Native public static final int SET_RADIAL_GRADIENT_PAINT = 104;
|
||||
@Native public static final int SET_TEXTURE_PAINT = 105;
|
||||
|
||||
// BufferedImageOp-related ops
|
||||
@Native public static final int ENABLE_CONVOLVE_OP = 120;
|
||||
@Native public static final int DISABLE_CONVOLVE_OP = 121;
|
||||
@Native public static final int ENABLE_RESCALE_OP = 122;
|
||||
@Native public static final int DISABLE_RESCALE_OP = 123;
|
||||
@Native public static final int ENABLE_LOOKUP_OP = 124;
|
||||
@Native public static final int DISABLE_LOOKUP_OP = 125;
|
||||
}
|
||||
535
jdkSrc/jdk8/sun/java2d/pipe/BufferedPaints.java
Normal file
535
jdkSrc/jdk8/sun/java2d/pipe/BufferedPaints.java
Normal file
@@ -0,0 +1,535 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Color;
|
||||
import java.awt.GradientPaint;
|
||||
import java.awt.LinearGradientPaint;
|
||||
import java.awt.MultipleGradientPaint;
|
||||
import java.awt.MultipleGradientPaint.ColorSpaceType;
|
||||
import java.awt.MultipleGradientPaint.CycleMethod;
|
||||
import java.awt.Paint;
|
||||
import java.awt.RadialGradientPaint;
|
||||
import java.awt.TexturePaint;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import sun.awt.image.PixelConverter;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
public class BufferedPaints {
|
||||
|
||||
static void setPaint(RenderQueue rq, SunGraphics2D sg2d,
|
||||
Paint paint, int ctxflags)
|
||||
{
|
||||
if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
|
||||
setColor(rq, sg2d.pixel);
|
||||
} else {
|
||||
boolean useMask = (ctxflags & BufferedContext.USE_MASK) != 0;
|
||||
switch (sg2d.paintState) {
|
||||
case SunGraphics2D.PAINT_GRADIENT:
|
||||
setGradientPaint(rq, sg2d,
|
||||
(GradientPaint)paint, useMask);
|
||||
break;
|
||||
case SunGraphics2D.PAINT_LIN_GRADIENT:
|
||||
setLinearGradientPaint(rq, sg2d,
|
||||
(LinearGradientPaint)paint, useMask);
|
||||
break;
|
||||
case SunGraphics2D.PAINT_RAD_GRADIENT:
|
||||
setRadialGradientPaint(rq, sg2d,
|
||||
(RadialGradientPaint)paint, useMask);
|
||||
break;
|
||||
case SunGraphics2D.PAINT_TEXTURE:
|
||||
setTexturePaint(rq, sg2d,
|
||||
(TexturePaint)paint, useMask);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void resetPaint(RenderQueue rq) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacity(4);
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
buf.putInt(RESET_PAINT);
|
||||
}
|
||||
|
||||
/****************************** Color support *******************************/
|
||||
|
||||
private static void setColor(RenderQueue rq, int pixel) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacity(8);
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
buf.putInt(SET_COLOR);
|
||||
buf.putInt(pixel);
|
||||
}
|
||||
|
||||
/************************* GradientPaint support ****************************/
|
||||
|
||||
/**
|
||||
* Note: This code is factored out into a separate static method
|
||||
* so that it can be shared by both the Gradient and LinearGradient
|
||||
* implementations. LinearGradient uses this code (for the
|
||||
* two-color sRGB case only) because it can be much faster than the
|
||||
* equivalent implementation that uses fragment shaders.
|
||||
*
|
||||
* We use OpenGL's texture coordinate generator to automatically
|
||||
* apply a smooth gradient (either cyclic or acyclic) to the geometry
|
||||
* being rendered. This technique is almost identical to the one
|
||||
* described in the comments for BufferedPaints.setTexturePaint(),
|
||||
* except the calculations take place in one dimension instead of two.
|
||||
* Instead of an anchor rectangle in the TexturePaint case, we use
|
||||
* the vector between the two GradientPaint end points in our
|
||||
* calculations. The generator uses a single plane equation that
|
||||
* takes the (x,y) location (in device space) of the fragment being
|
||||
* rendered to calculate a (u) texture coordinate for that fragment:
|
||||
* u = Ax + By + Cz + Dw
|
||||
*
|
||||
* The gradient renderer uses a two-pixel 1D texture where the first
|
||||
* pixel contains the first GradientPaint color, and the second pixel
|
||||
* contains the second GradientPaint color. (Note that we use the
|
||||
* GL_CLAMP_TO_EDGE wrapping mode for acyclic gradients so that we
|
||||
* clamp the colors properly at the extremes.) The following diagram
|
||||
* attempts to show the layout of the texture containing the two
|
||||
* GradientPaint colors (C1 and C2):
|
||||
*
|
||||
* +-----------------+
|
||||
* | C1 | C2 |
|
||||
* | | |
|
||||
* +-----------------+
|
||||
* u=0 .25 .5 .75 1
|
||||
*
|
||||
* We calculate our plane equation constants (A,B,D) such that u=0.25
|
||||
* corresponds to the first GradientPaint end point in user space and
|
||||
* u=0.75 corresponds to the second end point. This is somewhat
|
||||
* non-obvious, but since the gradient colors are generated by
|
||||
* interpolating between C1 and C2, we want the pure color at the
|
||||
* end points, and we will get the pure color only when u correlates
|
||||
* to the center of a texel. The following chart shows the expected
|
||||
* color for some sample values of u (where C' is the color halfway
|
||||
* between C1 and C2):
|
||||
*
|
||||
* u value acyclic (GL_CLAMP) cyclic (GL_REPEAT)
|
||||
* ------- ------------------ ------------------
|
||||
* -0.25 C1 C2
|
||||
* 0.0 C1 C'
|
||||
* 0.25 C1 C1
|
||||
* 0.5 C' C'
|
||||
* 0.75 C2 C2
|
||||
* 1.0 C2 C'
|
||||
* 1.25 C2 C1
|
||||
*
|
||||
* Original inspiration for this technique came from UMD's Agile2D
|
||||
* project (GradientManager.java).
|
||||
*/
|
||||
private static void setGradientPaint(RenderQueue rq, AffineTransform at,
|
||||
Color c1, Color c2,
|
||||
Point2D pt1, Point2D pt2,
|
||||
boolean isCyclic, boolean useMask)
|
||||
{
|
||||
// convert gradient colors to IntArgbPre format
|
||||
PixelConverter pc = PixelConverter.ArgbPre.instance;
|
||||
int pixel1 = pc.rgbToPixel(c1.getRGB(), null);
|
||||
int pixel2 = pc.rgbToPixel(c2.getRGB(), null);
|
||||
|
||||
// calculate plane equation constants
|
||||
double x = pt1.getX();
|
||||
double y = pt1.getY();
|
||||
at.translate(x, y);
|
||||
// now gradient point 1 is at the origin
|
||||
x = pt2.getX() - x;
|
||||
y = pt2.getY() - y;
|
||||
double len = Math.sqrt(x * x + y * y);
|
||||
at.rotate(x, y);
|
||||
// now gradient point 2 is on the positive x-axis
|
||||
at.scale(2*len, 1);
|
||||
// now gradient point 2 is at (0.5, 0)
|
||||
at.translate(-0.25, 0);
|
||||
// now gradient point 1 is at (0.25, 0), point 2 is at (0.75, 0)
|
||||
|
||||
double p0, p1, p3;
|
||||
try {
|
||||
at.invert();
|
||||
p0 = at.getScaleX();
|
||||
p1 = at.getShearX();
|
||||
p3 = at.getTranslateX();
|
||||
} catch (java.awt.geom.NoninvertibleTransformException e) {
|
||||
p0 = p1 = p3 = 0.0;
|
||||
}
|
||||
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacityAndAlignment(44, 12);
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
buf.putInt(SET_GRADIENT_PAINT);
|
||||
buf.putInt(useMask ? 1 : 0);
|
||||
buf.putInt(isCyclic ? 1 : 0);
|
||||
buf.putDouble(p0).putDouble(p1).putDouble(p3);
|
||||
buf.putInt(pixel1).putInt(pixel2);
|
||||
}
|
||||
|
||||
private static void setGradientPaint(RenderQueue rq,
|
||||
SunGraphics2D sg2d,
|
||||
GradientPaint paint,
|
||||
boolean useMask)
|
||||
{
|
||||
setGradientPaint(rq, (AffineTransform)sg2d.transform.clone(),
|
||||
paint.getColor1(), paint.getColor2(),
|
||||
paint.getPoint1(), paint.getPoint2(),
|
||||
paint.isCyclic(), useMask);
|
||||
}
|
||||
|
||||
/************************** TexturePaint support ****************************/
|
||||
|
||||
/**
|
||||
* We use OpenGL's texture coordinate generator to automatically
|
||||
* map the TexturePaint image to the geometry being rendered. The
|
||||
* generator uses two separate plane equations that take the (x,y)
|
||||
* location (in device space) of the fragment being rendered to
|
||||
* calculate (u,v) texture coordinates for that fragment:
|
||||
* u = Ax + By + Cz + Dw
|
||||
* v = Ex + Fy + Gz + Hw
|
||||
*
|
||||
* Since we use a 2D orthographic projection, we can assume that z=0
|
||||
* and w=1 for any fragment. So we need to calculate appropriate
|
||||
* values for the plane equation constants (A,B,D) and (E,F,H) such
|
||||
* that {u,v}=0 for the top-left of the TexturePaint's anchor
|
||||
* rectangle and {u,v}=1 for the bottom-right of the anchor rectangle.
|
||||
* We can easily make the texture image repeat for {u,v} values
|
||||
* outside the range [0,1] by specifying the GL_REPEAT texture wrap
|
||||
* mode.
|
||||
*
|
||||
* Calculating the plane equation constants is surprisingly simple.
|
||||
* We can think of it as an inverse matrix operation that takes
|
||||
* device space coordinates and transforms them into user space
|
||||
* coordinates that correspond to a location relative to the anchor
|
||||
* rectangle. First, we translate and scale the current user space
|
||||
* transform by applying the anchor rectangle bounds. We then take
|
||||
* the inverse of this affine transform. The rows of the resulting
|
||||
* inverse matrix correlate nicely to the plane equation constants
|
||||
* we were seeking.
|
||||
*/
|
||||
private static void setTexturePaint(RenderQueue rq,
|
||||
SunGraphics2D sg2d,
|
||||
TexturePaint paint,
|
||||
boolean useMask)
|
||||
{
|
||||
BufferedImage bi = paint.getImage();
|
||||
SurfaceData dstData = sg2d.surfaceData;
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
boolean filter =
|
||||
(sg2d.interpolationType !=
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
|
||||
|
||||
// calculate plane equation constants
|
||||
AffineTransform at = (AffineTransform)sg2d.transform.clone();
|
||||
Rectangle2D anchor = paint.getAnchorRect();
|
||||
at.translate(anchor.getX(), anchor.getY());
|
||||
at.scale(anchor.getWidth(), anchor.getHeight());
|
||||
|
||||
double xp0, xp1, xp3, yp0, yp1, yp3;
|
||||
try {
|
||||
at.invert();
|
||||
xp0 = at.getScaleX();
|
||||
xp1 = at.getShearX();
|
||||
xp3 = at.getTranslateX();
|
||||
yp0 = at.getShearY();
|
||||
yp1 = at.getScaleY();
|
||||
yp3 = at.getTranslateY();
|
||||
} catch (java.awt.geom.NoninvertibleTransformException e) {
|
||||
xp0 = xp1 = xp3 = yp0 = yp1 = yp3 = 0.0;
|
||||
}
|
||||
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacityAndAlignment(68, 12);
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
buf.putInt(SET_TEXTURE_PAINT);
|
||||
buf.putInt(useMask ? 1 : 0);
|
||||
buf.putInt(filter ? 1 : 0);
|
||||
buf.putLong(srcData.getNativeOps());
|
||||
buf.putDouble(xp0).putDouble(xp1).putDouble(xp3);
|
||||
buf.putDouble(yp0).putDouble(yp1).putDouble(yp3);
|
||||
}
|
||||
|
||||
/****************** Shared MultipleGradientPaint support ********************/
|
||||
|
||||
/**
|
||||
* The maximum number of gradient "stops" supported by our native
|
||||
* fragment shader implementations.
|
||||
*
|
||||
* This value has been empirically determined and capped to allow
|
||||
* our native shaders to run on all shader-level graphics hardware,
|
||||
* even on the older, more limited GPUs. Even the oldest Nvidia
|
||||
* hardware could handle 16, or even 32 fractions without any problem.
|
||||
* But the first-generation boards from ATI would fall back into
|
||||
* software mode (which is unusably slow) for values larger than 12;
|
||||
* it appears that those boards do not have enough native registers
|
||||
* to support the number of array accesses required by our gradient
|
||||
* shaders. So for now we will cap this value at 12, but we can
|
||||
* re-evaluate this in the future as hardware becomes more capable.
|
||||
*/
|
||||
@Native public static final int MULTI_MAX_FRACTIONS = 12;
|
||||
|
||||
/**
|
||||
* Helper function to convert a color component in sRGB space to
|
||||
* linear RGB space. Copied directly from the
|
||||
* MultipleGradientPaintContext class.
|
||||
*/
|
||||
public static int convertSRGBtoLinearRGB(int color) {
|
||||
float input, output;
|
||||
|
||||
input = color / 255.0f;
|
||||
if (input <= 0.04045f) {
|
||||
output = input / 12.92f;
|
||||
} else {
|
||||
output = (float)Math.pow((input + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
return Math.round(output * 255.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert a (non-premultiplied) Color in sRGB
|
||||
* space to an IntArgbPre pixel value, optionally in linear RGB space.
|
||||
* Based on the PixelConverter.ArgbPre.rgbToPixel() method.
|
||||
*/
|
||||
private static int colorToIntArgbPrePixel(Color c, boolean linear) {
|
||||
int rgb = c.getRGB();
|
||||
if (!linear && ((rgb >> 24) == -1)) {
|
||||
return rgb;
|
||||
}
|
||||
int a = rgb >>> 24;
|
||||
int r = (rgb >> 16) & 0xff;
|
||||
int g = (rgb >> 8) & 0xff;
|
||||
int b = (rgb ) & 0xff;
|
||||
if (linear) {
|
||||
r = convertSRGBtoLinearRGB(r);
|
||||
g = convertSRGBtoLinearRGB(g);
|
||||
b = convertSRGBtoLinearRGB(b);
|
||||
}
|
||||
int a2 = a + (a >> 7);
|
||||
r = (r * a2) >> 8;
|
||||
g = (g * a2) >> 8;
|
||||
b = (b * a2) >> 8;
|
||||
return ((a << 24) | (r << 16) | (g << 8) | (b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given array of Color objects into an int array
|
||||
* containing IntArgbPre pixel values. If the linear parameter
|
||||
* is true, the Color values will be converted into a linear RGB
|
||||
* color space before being returned.
|
||||
*/
|
||||
private static int[] convertToIntArgbPrePixels(Color[] colors,
|
||||
boolean linear)
|
||||
{
|
||||
int[] pixels = new int[colors.length];
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
pixels[i] = colorToIntArgbPrePixel(colors[i], linear);
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
/********************** LinearGradientPaint support *************************/
|
||||
|
||||
/**
|
||||
* This method uses techniques that are nearly identical to those
|
||||
* employed in setGradientPaint() above. The primary difference
|
||||
* is that at the native level we use a fragment shader to manually
|
||||
* apply the plane equation constants to the current fragment position
|
||||
* to calculate the gradient position in the range [0,1] (the native
|
||||
* code for GradientPaint does the same, except that it uses OpenGL's
|
||||
* automatic texture coordinate generation facilities).
|
||||
*
|
||||
* One other minor difference worth mentioning is that
|
||||
* setGradientPaint() calculates the plane equation constants
|
||||
* such that the gradient end points are positioned at 0.25 and 0.75
|
||||
* (for reasons discussed in the comments for that method). In
|
||||
* contrast, for LinearGradientPaint we setup the equation constants
|
||||
* such that the gradient end points fall at 0.0 and 1.0. The
|
||||
* reason for this difference is that in the fragment shader we
|
||||
* have more control over how the gradient values are interpreted
|
||||
* (depending on the paint's CycleMethod).
|
||||
*/
|
||||
private static void setLinearGradientPaint(RenderQueue rq,
|
||||
SunGraphics2D sg2d,
|
||||
LinearGradientPaint paint,
|
||||
boolean useMask)
|
||||
{
|
||||
boolean linear =
|
||||
(paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
|
||||
Color[] colors = paint.getColors();
|
||||
int numStops = colors.length;
|
||||
Point2D pt1 = paint.getStartPoint();
|
||||
Point2D pt2 = paint.getEndPoint();
|
||||
AffineTransform at = paint.getTransform();
|
||||
at.preConcatenate(sg2d.transform);
|
||||
|
||||
if (!linear && numStops == 2 &&
|
||||
paint.getCycleMethod() != CycleMethod.REPEAT)
|
||||
{
|
||||
// delegate to the optimized two-color gradient codepath
|
||||
boolean isCyclic =
|
||||
(paint.getCycleMethod() != CycleMethod.NO_CYCLE);
|
||||
setGradientPaint(rq, at,
|
||||
colors[0], colors[1],
|
||||
pt1, pt2,
|
||||
isCyclic, useMask);
|
||||
return;
|
||||
}
|
||||
|
||||
int cycleMethod = paint.getCycleMethod().ordinal();
|
||||
float[] fractions = paint.getFractions();
|
||||
int[] pixels = convertToIntArgbPrePixels(colors, linear);
|
||||
|
||||
// calculate plane equation constants
|
||||
double x = pt1.getX();
|
||||
double y = pt1.getY();
|
||||
at.translate(x, y);
|
||||
// now gradient point 1 is at the origin
|
||||
x = pt2.getX() - x;
|
||||
y = pt2.getY() - y;
|
||||
double len = Math.sqrt(x * x + y * y);
|
||||
at.rotate(x, y);
|
||||
// now gradient point 2 is on the positive x-axis
|
||||
at.scale(len, 1);
|
||||
// now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)
|
||||
|
||||
float p0, p1, p3;
|
||||
try {
|
||||
at.invert();
|
||||
p0 = (float)at.getScaleX();
|
||||
p1 = (float)at.getShearX();
|
||||
p3 = (float)at.getTranslateX();
|
||||
} catch (java.awt.geom.NoninvertibleTransformException e) {
|
||||
p0 = p1 = p3 = 0.0f;
|
||||
}
|
||||
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacity(20 + 12 + (numStops*4*2));
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
buf.putInt(SET_LINEAR_GRADIENT_PAINT);
|
||||
buf.putInt(useMask ? 1 : 0);
|
||||
buf.putInt(linear ? 1 : 0);
|
||||
buf.putInt(cycleMethod);
|
||||
buf.putInt(numStops);
|
||||
buf.putFloat(p0);
|
||||
buf.putFloat(p1);
|
||||
buf.putFloat(p3);
|
||||
buf.put(fractions);
|
||||
buf.put(pixels);
|
||||
}
|
||||
|
||||
/********************** RadialGradientPaint support *************************/
|
||||
|
||||
/**
|
||||
* This method calculates six m** values and a focusX value that
|
||||
* are used by the native fragment shader. These techniques are
|
||||
* based on a whitepaper by Daniel Rice on radial gradient performance
|
||||
* (attached to the bug report for 6521533). One can refer to that
|
||||
* document for the complete set of formulas and calculations, but
|
||||
* the basic goal is to compose a transform that will convert an
|
||||
* (x,y) position in device space into a "u" value that represents
|
||||
* the relative distance to the gradient focus point. The resulting
|
||||
* value can be used to look up the appropriate color by linearly
|
||||
* interpolating between the two nearest colors in the gradient.
|
||||
*/
|
||||
private static void setRadialGradientPaint(RenderQueue rq,
|
||||
SunGraphics2D sg2d,
|
||||
RadialGradientPaint paint,
|
||||
boolean useMask)
|
||||
{
|
||||
boolean linear =
|
||||
(paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
|
||||
int cycleMethod = paint.getCycleMethod().ordinal();
|
||||
float[] fractions = paint.getFractions();
|
||||
Color[] colors = paint.getColors();
|
||||
int numStops = colors.length;
|
||||
int[] pixels = convertToIntArgbPrePixels(colors, linear);
|
||||
Point2D center = paint.getCenterPoint();
|
||||
Point2D focus = paint.getFocusPoint();
|
||||
float radius = paint.getRadius();
|
||||
|
||||
// save original (untransformed) center and focus points
|
||||
double cx = center.getX();
|
||||
double cy = center.getY();
|
||||
double fx = focus.getX();
|
||||
double fy = focus.getY();
|
||||
|
||||
// transform from gradient coords to device coords
|
||||
AffineTransform at = paint.getTransform();
|
||||
at.preConcatenate(sg2d.transform);
|
||||
focus = at.transform(focus, focus);
|
||||
|
||||
// transform unit circle to gradient coords; we start with the
|
||||
// unit circle (center=(0,0), focus on positive x-axis, radius=1)
|
||||
// and then transform into gradient space
|
||||
at.translate(cx, cy);
|
||||
at.rotate(fx - cx, fy - cy);
|
||||
at.scale(radius, radius);
|
||||
|
||||
// invert to get mapping from device coords to unit circle
|
||||
try {
|
||||
at.invert();
|
||||
} catch (Exception e) {
|
||||
at.setToScale(0.0, 0.0);
|
||||
}
|
||||
focus = at.transform(focus, focus);
|
||||
|
||||
// clamp the focus point so that it does not rest on, or outside
|
||||
// of, the circumference of the gradient circle
|
||||
fx = Math.min(focus.getX(), 0.99);
|
||||
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacity(20 + 28 + (numStops*4*2));
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
buf.putInt(SET_RADIAL_GRADIENT_PAINT);
|
||||
buf.putInt(useMask ? 1 : 0);
|
||||
buf.putInt(linear ? 1 : 0);
|
||||
buf.putInt(numStops);
|
||||
buf.putInt(cycleMethod);
|
||||
buf.putFloat((float)at.getScaleX());
|
||||
buf.putFloat((float)at.getShearX());
|
||||
buf.putFloat((float)at.getTranslateX());
|
||||
buf.putFloat((float)at.getShearY());
|
||||
buf.putFloat((float)at.getScaleY());
|
||||
buf.putFloat((float)at.getTranslateY());
|
||||
buf.putFloat((float)fx);
|
||||
buf.put(fractions);
|
||||
buf.put(pixels);
|
||||
}
|
||||
}
|
||||
601
jdkSrc/jdk8/sun/java2d/pipe/BufferedRenderPipe.java
Normal file
601
jdkSrc/jdk8/sun/java2d/pipe/BufferedRenderPipe.java
Normal file
@@ -0,0 +1,601 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Polygon;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Arc2D;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.IllegalPathStateException;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.ProcessPath;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
/**
|
||||
* Base class for enqueuing rendering operations in a single-threaded
|
||||
* rendering environment. Instead of each operation being rendered
|
||||
* immediately by the underlying graphics library, the operation will be
|
||||
* added to the provided RenderQueue, which will be processed at a later
|
||||
* time by a single thread.
|
||||
*
|
||||
* This class provides implementations of drawLine(), drawRect(), drawPoly(),
|
||||
* fillRect(), draw(Shape), and fill(Shape), which are useful for a
|
||||
* hardware-accelerated renderer. The other draw*() and fill*() methods
|
||||
* simply delegate to draw(Shape) and fill(Shape), respectively.
|
||||
*/
|
||||
public abstract class BufferedRenderPipe
|
||||
implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, ParallelogramPipe
|
||||
{
|
||||
ParallelogramPipe aapgrampipe = new AAParallelogramPipe();
|
||||
|
||||
static final int BYTES_PER_POLY_POINT = 8;
|
||||
static final int BYTES_PER_SCANLINE = 12;
|
||||
static final int BYTES_PER_SPAN = 16;
|
||||
|
||||
protected RenderQueue rq;
|
||||
protected RenderBuffer buf;
|
||||
private BufferedDrawHandler drawHandler;
|
||||
|
||||
public BufferedRenderPipe(RenderQueue rq) {
|
||||
this.rq = rq;
|
||||
this.buf = rq.getBuffer();
|
||||
this.drawHandler = new BufferedDrawHandler();
|
||||
}
|
||||
|
||||
public ParallelogramPipe getAAParallelogramPipe() {
|
||||
return aapgrampipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the state in the provided SunGraphics2D object and sets up
|
||||
* any special resources for this operation (e.g. enabling gradient
|
||||
* shading).
|
||||
*/
|
||||
protected abstract void validateContext(SunGraphics2D sg2d);
|
||||
protected abstract void validateContextAA(SunGraphics2D sg2d);
|
||||
|
||||
public void drawLine(SunGraphics2D sg2d,
|
||||
int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int transx = sg2d.transX;
|
||||
int transy = sg2d.transY;
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d);
|
||||
rq.ensureCapacity(20);
|
||||
buf.putInt(DRAW_LINE);
|
||||
buf.putInt(x1 + transx);
|
||||
buf.putInt(y1 + transy);
|
||||
buf.putInt(x2 + transx);
|
||||
buf.putInt(y2 + transy);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawRect(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d);
|
||||
rq.ensureCapacity(20);
|
||||
buf.putInt(DRAW_RECT);
|
||||
buf.putInt(x + sg2d.transX);
|
||||
buf.putInt(y + sg2d.transY);
|
||||
buf.putInt(width);
|
||||
buf.putInt(height);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void fillRect(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d);
|
||||
rq.ensureCapacity(20);
|
||||
buf.putInt(FILL_RECT);
|
||||
buf.putInt(x + sg2d.transX);
|
||||
buf.putInt(y + sg2d.transY);
|
||||
buf.putInt(width);
|
||||
buf.putInt(height);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawRoundRect(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight)
|
||||
{
|
||||
draw(sg2d, new RoundRectangle2D.Float(x, y, width, height,
|
||||
arcWidth, arcHeight));
|
||||
}
|
||||
|
||||
public void fillRoundRect(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight)
|
||||
{
|
||||
fill(sg2d, new RoundRectangle2D.Float(x, y, width, height,
|
||||
arcWidth, arcHeight));
|
||||
}
|
||||
|
||||
public void drawOval(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
draw(sg2d, new Ellipse2D.Float(x, y, width, height));
|
||||
}
|
||||
|
||||
public void fillOval(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
fill(sg2d, new Ellipse2D.Float(x, y, width, height));
|
||||
}
|
||||
|
||||
public void drawArc(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle)
|
||||
{
|
||||
draw(sg2d, new Arc2D.Float(x, y, width, height,
|
||||
startAngle, arcAngle,
|
||||
Arc2D.OPEN));
|
||||
}
|
||||
|
||||
public void fillArc(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle)
|
||||
{
|
||||
fill(sg2d, new Arc2D.Float(x, y, width, height,
|
||||
startAngle, arcAngle,
|
||||
Arc2D.PIE));
|
||||
}
|
||||
|
||||
protected void drawPoly(final SunGraphics2D sg2d,
|
||||
final int[] xPoints, final int[] yPoints,
|
||||
final int nPoints, final boolean isClosed)
|
||||
{
|
||||
if (xPoints == null || yPoints == null) {
|
||||
throw new NullPointerException("coordinate array");
|
||||
}
|
||||
if (xPoints.length < nPoints || yPoints.length < nPoints) {
|
||||
throw new ArrayIndexOutOfBoundsException("coordinate array");
|
||||
}
|
||||
|
||||
if (nPoints < 2) {
|
||||
// render nothing
|
||||
return;
|
||||
} else if (nPoints == 2 && !isClosed) {
|
||||
// render a simple line
|
||||
drawLine(sg2d, xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d);
|
||||
|
||||
int pointBytesRequired = nPoints * BYTES_PER_POLY_POINT;
|
||||
int totalBytesRequired = 20 + pointBytesRequired;
|
||||
|
||||
if (totalBytesRequired <= buf.capacity()) {
|
||||
if (totalBytesRequired > buf.remaining()) {
|
||||
// process the queue first and then enqueue the points
|
||||
rq.flushNow();
|
||||
}
|
||||
buf.putInt(DRAW_POLY);
|
||||
// enqueue parameters
|
||||
buf.putInt(nPoints);
|
||||
buf.putInt(isClosed ? 1 : 0);
|
||||
buf.putInt(sg2d.transX);
|
||||
buf.putInt(sg2d.transY);
|
||||
// enqueue the points
|
||||
buf.put(xPoints, 0, nPoints);
|
||||
buf.put(yPoints, 0, nPoints);
|
||||
} else {
|
||||
// queue is too small to accommodate all points; perform the
|
||||
// operation directly on the queue flushing thread
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
drawPoly(xPoints, yPoints,
|
||||
nPoints, isClosed,
|
||||
sg2d.transX, sg2d.transY);
|
||||
}
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void drawPoly(int[] xPoints, int[] yPoints,
|
||||
int nPoints, boolean isClosed,
|
||||
int transX, int transY);
|
||||
|
||||
public void drawPolyline(SunGraphics2D sg2d,
|
||||
int[] xPoints, int[] yPoints,
|
||||
int nPoints)
|
||||
{
|
||||
drawPoly(sg2d, xPoints, yPoints, nPoints, false);
|
||||
}
|
||||
|
||||
public void drawPolygon(SunGraphics2D sg2d,
|
||||
int[] xPoints, int[] yPoints,
|
||||
int nPoints)
|
||||
{
|
||||
drawPoly(sg2d, xPoints, yPoints, nPoints, true);
|
||||
}
|
||||
|
||||
public void fillPolygon(SunGraphics2D sg2d,
|
||||
int[] xPoints, int[] yPoints,
|
||||
int nPoints)
|
||||
{
|
||||
fill(sg2d, new Polygon(xPoints, yPoints, nPoints));
|
||||
}
|
||||
|
||||
private class BufferedDrawHandler
|
||||
extends ProcessPath.DrawHandler
|
||||
{
|
||||
BufferedDrawHandler() {
|
||||
// these are bogus values; the caller will use validate()
|
||||
// to ensure that they are set properly prior to each usage
|
||||
super(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method needs to be called prior to each draw/fillPath()
|
||||
* operation to ensure the clip bounds are up to date.
|
||||
*/
|
||||
void validate(SunGraphics2D sg2d) {
|
||||
Region clip = sg2d.getCompClip();
|
||||
setBounds(clip.getLoX(), clip.getLoY(),
|
||||
clip.getHiX(), clip.getHiY(),
|
||||
sg2d.strokeHint);
|
||||
}
|
||||
|
||||
/**
|
||||
* drawPath() support...
|
||||
*/
|
||||
|
||||
public void drawLine(int x1, int y1, int x2, int y2) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacity(20);
|
||||
buf.putInt(DRAW_LINE);
|
||||
buf.putInt(x1);
|
||||
buf.putInt(y1);
|
||||
buf.putInt(x2);
|
||||
buf.putInt(y2);
|
||||
}
|
||||
|
||||
public void drawPixel(int x, int y) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
rq.ensureCapacity(12);
|
||||
buf.putInt(DRAW_PIXEL);
|
||||
buf.putInt(x);
|
||||
buf.putInt(y);
|
||||
}
|
||||
|
||||
/**
|
||||
* fillPath() support...
|
||||
*/
|
||||
|
||||
private int scanlineCount;
|
||||
private int scanlineCountIndex;
|
||||
private int remainingScanlines;
|
||||
|
||||
private void resetFillPath() {
|
||||
buf.putInt(DRAW_SCANLINES);
|
||||
scanlineCountIndex = buf.position();
|
||||
buf.putInt(0);
|
||||
scanlineCount = 0;
|
||||
remainingScanlines = buf.remaining() / BYTES_PER_SCANLINE;
|
||||
}
|
||||
|
||||
private void updateScanlineCount() {
|
||||
buf.putInt(scanlineCountIndex, scanlineCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from fillPath() to indicate that we are about to
|
||||
* start issuing drawScanline() calls.
|
||||
*/
|
||||
public void startFillPath() {
|
||||
rq.ensureCapacity(20); // to ensure room for at least a scanline
|
||||
resetFillPath();
|
||||
}
|
||||
|
||||
public void drawScanline(int x1, int x2, int y) {
|
||||
if (remainingScanlines == 0) {
|
||||
updateScanlineCount();
|
||||
rq.flushNow();
|
||||
resetFillPath();
|
||||
}
|
||||
buf.putInt(x1);
|
||||
buf.putInt(x2);
|
||||
buf.putInt(y);
|
||||
scanlineCount++;
|
||||
remainingScanlines--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from fillPath() to indicate that we are done
|
||||
* issuing drawScanline() calls.
|
||||
*/
|
||||
public void endFillPath() {
|
||||
updateScanlineCount();
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawPath(SunGraphics2D sg2d,
|
||||
Path2D.Float p2df, int transx, int transy)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d);
|
||||
drawHandler.validate(sg2d);
|
||||
ProcessPath.drawPath(drawHandler, p2df, transx, transy);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected void fillPath(SunGraphics2D sg2d,
|
||||
Path2D.Float p2df, int transx, int transy)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d);
|
||||
drawHandler.validate(sg2d);
|
||||
drawHandler.startFillPath();
|
||||
ProcessPath.fillPath(drawHandler, p2df, transx, transy);
|
||||
drawHandler.endFillPath();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private native int fillSpans(RenderQueue rq, long buf,
|
||||
int pos, int limit,
|
||||
SpanIterator si, long iterator,
|
||||
int transx, int transy);
|
||||
|
||||
protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
|
||||
int transx, int transy)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d);
|
||||
rq.ensureCapacity(24); // so that we have room for at least a span
|
||||
int newpos = fillSpans(rq, buf.getAddress(),
|
||||
buf.position(), buf.capacity(),
|
||||
si, si.getNativeIterator(),
|
||||
transx, transy);
|
||||
buf.position(newpos);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void fillParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d);
|
||||
rq.ensureCapacity(28);
|
||||
buf.putInt(FILL_PARALLELOGRAM);
|
||||
buf.putFloat((float) x);
|
||||
buf.putFloat((float) y);
|
||||
buf.putFloat((float) dx1);
|
||||
buf.putFloat((float) dy1);
|
||||
buf.putFloat((float) dx2);
|
||||
buf.putFloat((float) dy2);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d);
|
||||
rq.ensureCapacity(36);
|
||||
buf.putInt(DRAW_PARALLELOGRAM);
|
||||
buf.putFloat((float) x);
|
||||
buf.putFloat((float) y);
|
||||
buf.putFloat((float) dx1);
|
||||
buf.putFloat((float) dy1);
|
||||
buf.putFloat((float) dx2);
|
||||
buf.putFloat((float) dy2);
|
||||
buf.putFloat((float) lw1);
|
||||
buf.putFloat((float) lw2);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private class AAParallelogramPipe implements ParallelogramPipe {
|
||||
public void fillParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
validateContextAA(sg2d);
|
||||
rq.ensureCapacity(28);
|
||||
buf.putInt(FILL_AAPARALLELOGRAM);
|
||||
buf.putFloat((float) x);
|
||||
buf.putFloat((float) y);
|
||||
buf.putFloat((float) dx1);
|
||||
buf.putFloat((float) dy1);
|
||||
buf.putFloat((float) dx2);
|
||||
buf.putFloat((float) dy2);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
validateContextAA(sg2d);
|
||||
rq.ensureCapacity(36);
|
||||
buf.putInt(DRAW_AAPARALLELOGRAM);
|
||||
buf.putFloat((float) x);
|
||||
buf.putFloat((float) y);
|
||||
buf.putFloat((float) dx1);
|
||||
buf.putFloat((float) dy1);
|
||||
buf.putFloat((float) dx2);
|
||||
buf.putFloat((float) dy2);
|
||||
buf.putFloat((float) lw1);
|
||||
buf.putFloat((float) lw2);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(SunGraphics2D sg2d, Shape s) {
|
||||
if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {
|
||||
if (s instanceof Polygon) {
|
||||
if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
|
||||
Polygon p = (Polygon)s;
|
||||
drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Path2D.Float p2df;
|
||||
int transx, transy;
|
||||
if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
|
||||
if (s instanceof Path2D.Float) {
|
||||
p2df = (Path2D.Float)s;
|
||||
} else {
|
||||
p2df = new Path2D.Float(s);
|
||||
}
|
||||
transx = sg2d.transX;
|
||||
transy = sg2d.transY;
|
||||
} else {
|
||||
p2df = new Path2D.Float(s, sg2d.transform);
|
||||
transx = 0;
|
||||
transy = 0;
|
||||
}
|
||||
drawPath(sg2d, p2df, transx, transy);
|
||||
} else if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
|
||||
ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);
|
||||
try {
|
||||
fillSpans(sg2d, si, 0, 0);
|
||||
} finally {
|
||||
si.dispose();
|
||||
}
|
||||
} else {
|
||||
fill(sg2d, sg2d.stroke.createStrokedShape(s));
|
||||
}
|
||||
}
|
||||
|
||||
public void fill(SunGraphics2D sg2d, Shape s) {
|
||||
int transx, transy;
|
||||
|
||||
if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {
|
||||
// Here we are able to use fillPath() for
|
||||
// high-quality fills.
|
||||
Path2D.Float p2df;
|
||||
if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
|
||||
if (s instanceof Path2D.Float) {
|
||||
p2df = (Path2D.Float)s;
|
||||
} else {
|
||||
p2df = new Path2D.Float(s);
|
||||
}
|
||||
transx = sg2d.transX;
|
||||
transy = sg2d.transY;
|
||||
} else {
|
||||
p2df = new Path2D.Float(s, sg2d.transform);
|
||||
transx = 0;
|
||||
transy = 0;
|
||||
}
|
||||
fillPath(sg2d, p2df, transx, transy);
|
||||
return;
|
||||
}
|
||||
|
||||
AffineTransform at;
|
||||
if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
|
||||
// Transform (translation) will be done by FillSpans (we could
|
||||
// delegate to fillPolygon() here, but most hardware accelerated
|
||||
// libraries cannot handle non-convex polygons, so we will use
|
||||
// the FillSpans approach by default)
|
||||
at = null;
|
||||
transx = sg2d.transX;
|
||||
transy = sg2d.transY;
|
||||
} else {
|
||||
// Transform will be done by the PathIterator
|
||||
at = sg2d.transform;
|
||||
transx = transy = 0;
|
||||
}
|
||||
|
||||
ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
|
||||
try {
|
||||
// Subtract transx/y from the SSI clip to match the
|
||||
// (potentially untranslated) geometry fed to it
|
||||
Region clip = sg2d.getCompClip();
|
||||
ssi.setOutputAreaXYXY(clip.getLoX() - transx,
|
||||
clip.getLoY() - transy,
|
||||
clip.getHiX() - transx,
|
||||
clip.getHiY() - transy);
|
||||
ssi.appendPath(s.getPathIterator(at));
|
||||
fillSpans(sg2d, ssi, transx, transy);
|
||||
} finally {
|
||||
ssi.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
170
jdkSrc/jdk8/sun/java2d/pipe/BufferedTextPipe.java
Normal file
170
jdkSrc/jdk8/sun/java2d/pipe/BufferedTextPipe.java
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.AlphaComposite;
|
||||
import java.awt.Composite;
|
||||
import sun.font.GlyphList;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
public abstract class BufferedTextPipe extends GlyphListPipe {
|
||||
|
||||
@Native private static final int BYTES_PER_GLYPH_IMAGE = 8;
|
||||
@Native private static final int BYTES_PER_GLYPH_POSITION = 8;
|
||||
|
||||
/**
|
||||
* The following offsets are used to pack the parameters in
|
||||
* createPackedParams(). (They are also used at the native level when
|
||||
* unpacking the params.)
|
||||
*/
|
||||
@Native private static final int OFFSET_CONTRAST = 8;
|
||||
@Native private static final int OFFSET_RGBORDER = 2;
|
||||
@Native private static final int OFFSET_SUBPIXPOS = 1;
|
||||
@Native private static final int OFFSET_POSITIONS = 0;
|
||||
|
||||
/**
|
||||
* Packs the given parameters into a single int value in order to save
|
||||
* space on the rendering queue. Note that most of these parameters
|
||||
* are only used for rendering LCD-optimized text, but conditionalizing
|
||||
* this work wouldn't make any impact on performance, so we will pack
|
||||
* those parameters even in the non-LCD case.
|
||||
*/
|
||||
private static int createPackedParams(SunGraphics2D sg2d, GlyphList gl) {
|
||||
return
|
||||
(((gl.usePositions() ? 1 : 0) << OFFSET_POSITIONS) |
|
||||
((gl.isSubPixPos() ? 1 : 0) << OFFSET_SUBPIXPOS) |
|
||||
((gl.isRGBOrder() ? 1 : 0) << OFFSET_RGBORDER ) |
|
||||
((sg2d.lcdTextContrast & 0xff) << OFFSET_CONTRAST ));
|
||||
}
|
||||
|
||||
protected final RenderQueue rq;
|
||||
|
||||
protected BufferedTextPipe(RenderQueue rq) {
|
||||
this.rq = rq;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
|
||||
/*
|
||||
* The native drawGlyphList() only works with two composite types:
|
||||
* - CompositeType.SrcOver (with any extra alpha), or
|
||||
* - CompositeType.Xor
|
||||
*/
|
||||
Composite comp = sg2d.composite;
|
||||
if (comp == AlphaComposite.Src) {
|
||||
/*
|
||||
* In addition to the composite types listed above, the logic
|
||||
* in OGL/D3DSurfaceData.validatePipe() allows for
|
||||
* CompositeType.SrcNoEa, but only in the presence of an opaque
|
||||
* color. If we reach this case, we know the color is opaque,
|
||||
* and therefore SrcNoEa is the same as SrcOverNoEa, so we
|
||||
* override the composite here.
|
||||
*/
|
||||
comp = AlphaComposite.SrcOver;
|
||||
}
|
||||
|
||||
rq.lock();
|
||||
try {
|
||||
validateContext(sg2d, comp);
|
||||
enqueueGlyphList(sg2d, gl);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void enqueueGlyphList(final SunGraphics2D sg2d,
|
||||
final GlyphList gl)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
final int totalGlyphs = gl.getNumGlyphs();
|
||||
int glyphBytesRequired = totalGlyphs * BYTES_PER_GLYPH_IMAGE;
|
||||
int posBytesRequired =
|
||||
gl.usePositions() ? totalGlyphs * BYTES_PER_GLYPH_POSITION : 0;
|
||||
int totalBytesRequired = 24 + glyphBytesRequired + posBytesRequired;
|
||||
|
||||
final long[] images = gl.getImages();
|
||||
final float glyphListOrigX = gl.getX() + 0.5f;
|
||||
final float glyphListOrigY = gl.getY() + 0.5f;
|
||||
|
||||
// make sure the RenderQueue keeps a hard reference to the FontStrike
|
||||
// so that the associated glyph images are not disposed while enqueued
|
||||
rq.addReference(gl.getStrike());
|
||||
|
||||
if (totalBytesRequired <= buf.capacity()) {
|
||||
if (totalBytesRequired > buf.remaining()) {
|
||||
// process the queue first and then enqueue the glyphs
|
||||
rq.flushNow();
|
||||
}
|
||||
rq.ensureAlignment(20);
|
||||
buf.putInt(DRAW_GLYPH_LIST);
|
||||
// enqueue parameters
|
||||
buf.putInt(totalGlyphs);
|
||||
buf.putInt(createPackedParams(sg2d, gl));
|
||||
buf.putFloat(glyphListOrigX);
|
||||
buf.putFloat(glyphListOrigY);
|
||||
// now enqueue glyph information
|
||||
buf.put(images, 0, totalGlyphs);
|
||||
if (gl.usePositions()) {
|
||||
float[] positions = gl.getPositions();
|
||||
buf.put(positions, 0, 2*totalGlyphs);
|
||||
}
|
||||
} else {
|
||||
// queue is too small to accommodate glyphs; perform
|
||||
// the operation directly on the queue flushing thread
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
drawGlyphList(totalGlyphs, gl.usePositions(),
|
||||
gl.isSubPixPos(), gl.isRGBOrder(),
|
||||
sg2d.lcdTextContrast,
|
||||
glyphListOrigX, glyphListOrigY,
|
||||
images, gl.getPositions());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called as a separate Runnable when the operation is too large to fit
|
||||
* on the RenderQueue. The OGL/D3D pipelines each have their own (small)
|
||||
* native implementation of this method.
|
||||
*/
|
||||
protected abstract void drawGlyphList(int numGlyphs, boolean usePositions,
|
||||
boolean subPixPos, boolean rgbOrder,
|
||||
int lcdContrast,
|
||||
float glOrigX, float glOrigY,
|
||||
long[] images, float[] positions);
|
||||
|
||||
/**
|
||||
* Validates the state in the provided SunGraphics2D object.
|
||||
*/
|
||||
protected abstract void validateContext(SunGraphics2D sg2d,
|
||||
Composite comp);
|
||||
}
|
||||
50
jdkSrc/jdk8/sun/java2d/pipe/CompositePipe.java
Normal file
50
jdkSrc/jdk8/sun/java2d/pipe/CompositePipe.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This interface defines the set of calls used by a rendering pipeline
|
||||
* based on an AATileGenerator to communicate the alpha tile sequence
|
||||
* to the output (compositing) stages of the pipeline.
|
||||
*/
|
||||
public interface CompositePipe {
|
||||
public Object startSequence(SunGraphics2D sg, Shape s, Rectangle dev,
|
||||
int[] abox);
|
||||
|
||||
public boolean needTile(Object context, int x, int y, int w, int h);
|
||||
|
||||
public void renderPathTile(Object context,
|
||||
byte[] atile, int offset, int tilesize,
|
||||
int x, int y, int w, int h);
|
||||
|
||||
public void skipTile(Object context, int x, int y);
|
||||
|
||||
public void endSequence(Object context);
|
||||
}
|
||||
1120
jdkSrc/jdk8/sun/java2d/pipe/DrawImage.java
Normal file
1120
jdkSrc/jdk8/sun/java2d/pipe/DrawImage.java
Normal file
File diff suppressed because it is too large
Load Diff
86
jdkSrc/jdk8/sun/java2d/pipe/DrawImagePipe.java
Normal file
86
jdkSrc/jdk8/sun/java2d/pipe/DrawImagePipe.java
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Color;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This interface defines the set of calls that pipeline objects
|
||||
* can use to pass on responsibility for performing various
|
||||
* image copy commands.
|
||||
* There are 3 types of image copies handled by this class:
|
||||
* - copyImage: These methods simply copy the pixels
|
||||
* from the src to dest, either from (0, 0) (implicit)
|
||||
* or from a given (sx, sy) location.
|
||||
* - scaleImage: These methods copy from src to dest while
|
||||
* scaling the source image. The src and dest rectangles
|
||||
* are used to specify the scale.
|
||||
* - copyImageBg: These methods behave the same as the
|
||||
* copyImage methods except they substitute the given
|
||||
* background color for any transparent pixels.
|
||||
* - scaleImageBg: These methods behave the same as the
|
||||
* scaleImage methods except they substitute the given
|
||||
* background color for any transparent pixels.
|
||||
* - transformImage....
|
||||
*/
|
||||
public interface DrawImagePipe {
|
||||
|
||||
public boolean copyImage(SunGraphics2D sg, Image img,
|
||||
int x, int y,
|
||||
Color bgColor,
|
||||
ImageObserver observer);
|
||||
|
||||
public boolean copyImage(SunGraphics2D sg, Image img,
|
||||
int dx, int dy, int sx, int sy, int w, int h,
|
||||
Color bgColor,
|
||||
ImageObserver observer);
|
||||
|
||||
public boolean scaleImage(SunGraphics2D sg, Image img, int x, int y,
|
||||
int width, int height,
|
||||
Color bgColor,
|
||||
ImageObserver observer);
|
||||
|
||||
public boolean scaleImage(SunGraphics2D sg, Image img,
|
||||
int dx1, int dy1, int dx2, int dy2,
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
Color bgColor,
|
||||
ImageObserver observer);
|
||||
|
||||
public boolean transformImage(SunGraphics2D sg, Image img,
|
||||
AffineTransform atfm,
|
||||
ImageObserver observer);
|
||||
|
||||
public void transformImage(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp op, int x, int y);
|
||||
|
||||
|
||||
}
|
||||
154
jdkSrc/jdk8/sun/java2d/pipe/GeneralCompositePipe.java
Normal file
154
jdkSrc/jdk8/sun/java2d/pipe/GeneralCompositePipe.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2002, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.AlphaComposite;
|
||||
import java.awt.CompositeContext;
|
||||
import java.awt.PaintContext;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import sun.awt.image.BufImgSurfaceData;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.MaskBlit;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
|
||||
public class GeneralCompositePipe implements CompositePipe {
|
||||
class TileContext {
|
||||
SunGraphics2D sunG2D;
|
||||
PaintContext paintCtxt;
|
||||
CompositeContext compCtxt;
|
||||
ColorModel compModel;
|
||||
Object pipeState;
|
||||
|
||||
public TileContext(SunGraphics2D sg, PaintContext pCtx,
|
||||
CompositeContext cCtx, ColorModel cModel) {
|
||||
sunG2D = sg;
|
||||
paintCtxt = pCtx;
|
||||
compCtxt = cCtx;
|
||||
compModel = cModel;
|
||||
}
|
||||
}
|
||||
|
||||
public Object startSequence(SunGraphics2D sg, Shape s, Rectangle devR,
|
||||
int[] abox) {
|
||||
RenderingHints hints = sg.getRenderingHints();
|
||||
ColorModel model = sg.getDeviceColorModel();
|
||||
PaintContext paintContext =
|
||||
sg.paint.createContext(model, devR, s.getBounds2D(),
|
||||
sg.cloneTransform(),
|
||||
hints);
|
||||
CompositeContext compositeContext =
|
||||
sg.composite.createContext(paintContext.getColorModel(), model,
|
||||
hints);
|
||||
return new TileContext(sg, paintContext, compositeContext, model);
|
||||
}
|
||||
|
||||
public boolean needTile(Object ctx, int x, int y, int w, int h) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* GeneralCompositePipe.renderPathTile works with custom composite operator
|
||||
* provided by an application
|
||||
*/
|
||||
public void renderPathTile(Object ctx,
|
||||
byte[] atile, int offset, int tilesize,
|
||||
int x, int y, int w, int h) {
|
||||
TileContext context = (TileContext) ctx;
|
||||
PaintContext paintCtxt = context.paintCtxt;
|
||||
CompositeContext compCtxt = context.compCtxt;
|
||||
SunGraphics2D sg = context.sunG2D;
|
||||
|
||||
Raster srcRaster = paintCtxt.getRaster(x, y, w, h);
|
||||
ColorModel paintModel = paintCtxt.getColorModel();
|
||||
|
||||
Raster dstRaster;
|
||||
Raster dstIn;
|
||||
WritableRaster dstOut;
|
||||
|
||||
SurfaceData sd = sg.getSurfaceData();
|
||||
dstRaster = sd.getRaster(x, y, w, h);
|
||||
if (dstRaster instanceof WritableRaster && atile == null) {
|
||||
dstOut = (WritableRaster) dstRaster;
|
||||
dstOut = dstOut.createWritableChild(x, y, w, h, 0, 0, null);
|
||||
dstIn = dstOut;
|
||||
} else {
|
||||
dstIn = dstRaster.createChild(x, y, w, h, 0, 0, null);
|
||||
dstOut = dstIn.createCompatibleWritableRaster();
|
||||
}
|
||||
|
||||
compCtxt.compose(srcRaster, dstIn, dstOut);
|
||||
|
||||
if (dstRaster != dstOut && dstOut.getParent() != dstRaster) {
|
||||
if (dstRaster instanceof WritableRaster && atile == null) {
|
||||
((WritableRaster) dstRaster).setDataElements(x, y, dstOut);
|
||||
} else {
|
||||
ColorModel cm = sg.getDeviceColorModel();
|
||||
BufferedImage resImg =
|
||||
new BufferedImage(cm, dstOut,
|
||||
cm.isAlphaPremultiplied(),
|
||||
null);
|
||||
SurfaceData resData = BufImgSurfaceData.createData(resImg);
|
||||
if (atile == null) {
|
||||
Blit blit = Blit.getFromCache(resData.getSurfaceType(),
|
||||
CompositeType.SrcNoEa,
|
||||
sd.getSurfaceType());
|
||||
blit.Blit(resData, sd, AlphaComposite.Src, null,
|
||||
0, 0, x, y, w, h);
|
||||
} else {
|
||||
MaskBlit blit = MaskBlit.getFromCache(resData.getSurfaceType(),
|
||||
CompositeType.SrcNoEa,
|
||||
sd.getSurfaceType());
|
||||
blit.MaskBlit(resData, sd, AlphaComposite.Src, null,
|
||||
0, 0, x, y, w, h,
|
||||
atile, offset, tilesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void skipTile(Object ctx, int x, int y) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void endSequence(Object ctx) {
|
||||
TileContext context = (TileContext) ctx;
|
||||
if (context.paintCtxt != null) {
|
||||
context.paintCtxt.dispose();
|
||||
}
|
||||
if (context.compCtxt != null) {
|
||||
context.compCtxt.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
60
jdkSrc/jdk8/sun/java2d/pipe/GlyphListLoopPipe.java
Normal file
60
jdkSrc/jdk8/sun/java2d/pipe/GlyphListLoopPipe.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.font.GlyphVector;
|
||||
import sun.awt.SunHints;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.font.GlyphList;
|
||||
|
||||
/**
|
||||
* A delegate pipe of SG2D which implements redispatching of
|
||||
* for the src mode loops in the drawGlyphVector case where
|
||||
* the installed loop may not match the glyphvector.
|
||||
*/
|
||||
|
||||
public abstract class GlyphListLoopPipe extends GlyphListPipe
|
||||
implements LoopBasedPipe
|
||||
{
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl,
|
||||
int aaHint) {
|
||||
switch (aaHint) {
|
||||
case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
|
||||
sg2d.loops.drawGlyphListLoop.
|
||||
DrawGlyphList(sg2d, sg2d.surfaceData, gl);
|
||||
return;
|
||||
case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
|
||||
sg2d.loops.drawGlyphListAALoop.
|
||||
DrawGlyphListAA(sg2d, sg2d.surfaceData, gl);
|
||||
return;
|
||||
case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
|
||||
case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:
|
||||
sg2d.loops.drawGlyphListLCDLoop.
|
||||
DrawGlyphListLCD(sg2d,sg2d.surfaceData, gl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
147
jdkSrc/jdk8/sun/java2d/pipe/GlyphListPipe.java
Normal file
147
jdkSrc/jdk8/sun/java2d/pipe/GlyphListPipe.java
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Font;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.TextLayout;
|
||||
|
||||
import sun.awt.SunHints;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.font.GlyphList;
|
||||
import sun.java2d.loops.FontInfo;
|
||||
|
||||
/**
|
||||
* A delegate pipe of SG2D for drawing text.
|
||||
*/
|
||||
|
||||
public abstract class GlyphListPipe implements TextPipe {
|
||||
|
||||
public void drawString(SunGraphics2D sg2d, String s,
|
||||
double x, double y)
|
||||
{
|
||||
FontInfo info = sg2d.getFontInfo();
|
||||
if (info.pixelHeight > OutlineTextRenderer.THRESHHOLD) {
|
||||
SurfaceData.outlineTextRenderer.drawString(sg2d, s, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
float devx, devy;
|
||||
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
|
||||
double origin[] = {x + info.originX, y + info.originY};
|
||||
sg2d.transform.transform(origin, 0, origin, 0, 1);
|
||||
devx = (float)origin[0];
|
||||
devy = (float)origin[1];
|
||||
} else {
|
||||
devx = (float)(x + info.originX + sg2d.transX);
|
||||
devy = (float)(y + info.originY + sg2d.transY);
|
||||
}
|
||||
/* setFromString returns false if shaping is needed, and we then back
|
||||
* off to a TextLayout. Such text may benefit slightly from a lower
|
||||
* overhead in this approach over the approach in previous releases.
|
||||
*/
|
||||
GlyphList gl = GlyphList.getInstance();
|
||||
if (gl.setFromString(info, s, devx, devy)) {
|
||||
drawGlyphList(sg2d, gl);
|
||||
gl.dispose();
|
||||
} else {
|
||||
gl.dispose(); // release this asap.
|
||||
TextLayout tl = new TextLayout(s, sg2d.getFont(),
|
||||
sg2d.getFontRenderContext());
|
||||
tl.draw(sg2d, (float)x, (float)y);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawChars(SunGraphics2D sg2d,
|
||||
char data[], int offset, int length,
|
||||
int ix, int iy)
|
||||
{
|
||||
FontInfo info = sg2d.getFontInfo();
|
||||
float x, y;
|
||||
if (info.pixelHeight > OutlineTextRenderer.THRESHHOLD) {
|
||||
SurfaceData.outlineTextRenderer.drawChars(
|
||||
sg2d, data, offset, length, ix, iy);
|
||||
return;
|
||||
}
|
||||
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
|
||||
double origin[] = {ix + info.originX, iy + info.originY};
|
||||
sg2d.transform.transform(origin, 0, origin, 0, 1);
|
||||
x = (float) origin[0];
|
||||
y = (float) origin[1];
|
||||
} else {
|
||||
x = ix + info.originX + sg2d.transX;
|
||||
y = iy + info.originY + sg2d.transY;
|
||||
}
|
||||
GlyphList gl = GlyphList.getInstance();
|
||||
if (gl.setFromChars(info, data, offset, length, x, y)) {
|
||||
drawGlyphList(sg2d, gl);
|
||||
gl.dispose();
|
||||
} else {
|
||||
gl.dispose(); // release this asap.
|
||||
TextLayout tl = new TextLayout(new String(data, offset, length),
|
||||
sg2d.getFont(),
|
||||
sg2d.getFontRenderContext());
|
||||
tl.draw(sg2d, ix, iy);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void drawGlyphVector(SunGraphics2D sg2d, GlyphVector gv,
|
||||
float x, float y)
|
||||
{
|
||||
FontRenderContext frc = gv.getFontRenderContext();
|
||||
FontInfo info = sg2d.getGVFontInfo(gv.getFont(), frc);
|
||||
if (info.pixelHeight > OutlineTextRenderer.THRESHHOLD) {
|
||||
SurfaceData.outlineTextRenderer.drawGlyphVector(sg2d, gv, x, y);
|
||||
return;
|
||||
}
|
||||
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
|
||||
double origin[] = {x, y};
|
||||
sg2d.transform.transform(origin, 0, origin, 0, 1);
|
||||
x = (float) origin[0];
|
||||
y = (float) origin[1];
|
||||
} else {
|
||||
x += sg2d.transX; // don't use the glyph info origin, already in gv.
|
||||
y += sg2d.transY;
|
||||
}
|
||||
|
||||
GlyphList gl = GlyphList.getInstance();
|
||||
gl.setFromGlyphVector(info, gv, x, y);
|
||||
drawGlyphList(sg2d, gl, info.aaHint);
|
||||
gl.dispose();
|
||||
}
|
||||
|
||||
protected abstract void drawGlyphList(SunGraphics2D sg2d, GlyphList gl);
|
||||
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl,
|
||||
int aaHint) {
|
||||
drawGlyphList(sg2d, gl);
|
||||
}
|
||||
}
|
||||
44
jdkSrc/jdk8/sun/java2d/pipe/LCDTextRenderer.java
Normal file
44
jdkSrc/jdk8/sun/java2d/pipe/LCDTextRenderer.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.font.GlyphVector;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.font.GlyphList;
|
||||
import static sun.awt.SunHints.*;
|
||||
|
||||
/**
|
||||
* A delegate pipe of SG2D for drawing LCD text with
|
||||
* a solid source colour to an opaque destination.
|
||||
*/
|
||||
|
||||
public class LCDTextRenderer extends GlyphListLoopPipe {
|
||||
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
|
||||
sg2d.loops.drawGlyphListLCDLoop.
|
||||
DrawGlyphListLCD(sg2d, sg2d.surfaceData, gl);
|
||||
}
|
||||
}
|
||||
37
jdkSrc/jdk8/sun/java2d/pipe/LoopBasedPipe.java
Normal file
37
jdkSrc/jdk8/sun/java2d/pipe/LoopBasedPipe.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* This is a marker interface used by Pipes that need RenderLoops.
|
||||
* RenderLoops are validated in SurfaceData when a pipe is recognised to
|
||||
* implement this interface.
|
||||
*
|
||||
* @author Mario Torre <neugens@aicas.com>
|
||||
*/
|
||||
public interface LoopBasedPipe {
|
||||
|
||||
}
|
||||
377
jdkSrc/jdk8/sun/java2d/pipe/LoopPipe.java
Normal file
377
jdkSrc/jdk8/sun/java2d/pipe/LoopPipe.java
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Font;
|
||||
import java.awt.Shape;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Arc2D;
|
||||
import java.awt.geom.IllegalPathStateException;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.font.GlyphVector;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.FontInfo;
|
||||
import sun.java2d.loops.DrawPolygons;
|
||||
import sun.java2d.loops.FillParallelogram;
|
||||
import sun.java2d.loops.DrawParallelogram;
|
||||
import sun.awt.SunHints;
|
||||
|
||||
public class LoopPipe
|
||||
implements PixelDrawPipe,
|
||||
PixelFillPipe,
|
||||
ParallelogramPipe,
|
||||
ShapeDrawPipe,
|
||||
LoopBasedPipe
|
||||
{
|
||||
final static RenderingEngine RenderEngine = RenderingEngine.getInstance();
|
||||
|
||||
public void drawLine(SunGraphics2D sg2d,
|
||||
int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int tX = sg2d.transX;
|
||||
int tY = sg2d.transY;
|
||||
sg2d.loops.drawLineLoop.DrawLine(sg2d, sg2d.getSurfaceData(),
|
||||
x1 + tX, y1 + tY,
|
||||
x2 + tX, y2 + tY);
|
||||
}
|
||||
|
||||
public void drawRect(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
sg2d.loops.drawRectLoop.DrawRect(sg2d, sg2d.getSurfaceData(),
|
||||
x + sg2d.transX,
|
||||
y + sg2d.transY,
|
||||
width, height);
|
||||
}
|
||||
|
||||
public void drawRoundRect(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight)
|
||||
{
|
||||
sg2d.shapepipe.draw(sg2d,
|
||||
new RoundRectangle2D.Float(x, y, width, height,
|
||||
arcWidth, arcHeight));
|
||||
}
|
||||
|
||||
public void drawOval(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
sg2d.shapepipe.draw(sg2d, new Ellipse2D.Float(x, y, width, height));
|
||||
}
|
||||
|
||||
public void drawArc(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle)
|
||||
{
|
||||
sg2d.shapepipe.draw(sg2d, new Arc2D.Float(x, y, width, height,
|
||||
startAngle, arcAngle,
|
||||
Arc2D.OPEN));
|
||||
}
|
||||
|
||||
public void drawPolyline(SunGraphics2D sg2d,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints)
|
||||
{
|
||||
int nPointsArray[] = { nPoints };
|
||||
sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d.getSurfaceData(),
|
||||
xPoints, yPoints,
|
||||
nPointsArray, 1,
|
||||
sg2d.transX, sg2d.transY,
|
||||
false);
|
||||
}
|
||||
|
||||
public void drawPolygon(SunGraphics2D sg2d,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints)
|
||||
{
|
||||
int nPointsArray[] = { nPoints };
|
||||
sg2d.loops.drawPolygonsLoop.DrawPolygons(sg2d, sg2d.getSurfaceData(),
|
||||
xPoints, yPoints,
|
||||
nPointsArray, 1,
|
||||
sg2d.transX, sg2d.transY,
|
||||
true);
|
||||
}
|
||||
|
||||
public void fillRect(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
sg2d.loops.fillRectLoop.FillRect(sg2d, sg2d.getSurfaceData(),
|
||||
x + sg2d.transX,
|
||||
y + sg2d.transY,
|
||||
width, height);
|
||||
}
|
||||
|
||||
public void fillRoundRect(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight)
|
||||
{
|
||||
sg2d.shapepipe.fill(sg2d,
|
||||
new RoundRectangle2D.Float(x, y, width, height,
|
||||
arcWidth, arcHeight));
|
||||
}
|
||||
|
||||
public void fillOval(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
sg2d.shapepipe.fill(sg2d, new Ellipse2D.Float(x, y, width, height));
|
||||
}
|
||||
|
||||
public void fillArc(SunGraphics2D sg2d,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle)
|
||||
{
|
||||
sg2d.shapepipe.fill(sg2d, new Arc2D.Float(x, y, width, height,
|
||||
startAngle, arcAngle,
|
||||
Arc2D.PIE));
|
||||
}
|
||||
|
||||
public void fillPolygon(SunGraphics2D sg2d,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints)
|
||||
{
|
||||
ShapeSpanIterator sr = getFillSSI(sg2d);
|
||||
|
||||
try {
|
||||
sr.setOutputArea(sg2d.getCompClip());
|
||||
sr.appendPoly(xPoints, yPoints, nPoints, sg2d.transX, sg2d.transY);
|
||||
fillSpans(sg2d, sr);
|
||||
} finally {
|
||||
sr.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void draw(SunGraphics2D sg2d, Shape s) {
|
||||
if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {
|
||||
Path2D.Float p2df;
|
||||
int transX;
|
||||
int transY;
|
||||
if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
|
||||
if (s instanceof Path2D.Float) {
|
||||
p2df = (Path2D.Float)s;
|
||||
} else {
|
||||
p2df = new Path2D.Float(s);
|
||||
}
|
||||
transX = sg2d.transX;
|
||||
transY = sg2d.transY;
|
||||
} else {
|
||||
p2df = new Path2D.Float(s, sg2d.transform);
|
||||
transX = 0;
|
||||
transY = 0;
|
||||
}
|
||||
sg2d.loops.drawPathLoop.DrawPath(sg2d, sg2d.getSurfaceData(),
|
||||
transX, transY, p2df);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sg2d.strokeState == SunGraphics2D.STROKE_CUSTOM) {
|
||||
fill(sg2d, sg2d.stroke.createStrokedShape(s));
|
||||
return;
|
||||
}
|
||||
|
||||
ShapeSpanIterator sr = getStrokeSpans(sg2d, s);
|
||||
|
||||
try {
|
||||
fillSpans(sg2d, sr);
|
||||
} finally {
|
||||
sr.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a ShapeSpanIterator instance that normalizes as
|
||||
* appropriate for a fill operation as per the settings in
|
||||
* the specified SunGraphics2D object.
|
||||
*
|
||||
* The ShapeSpanIterator will be newly constructed and ready
|
||||
* to start taking in geometry.
|
||||
*
|
||||
* Note that the caller is responsible for calling dispose()
|
||||
* on the returned ShapeSpanIterator inside a try/finally block:
|
||||
* <pre>
|
||||
* ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
|
||||
* try {
|
||||
* ssi.setOutputArea(clip);
|
||||
* ssi.appendPath(...); // or appendPoly
|
||||
* // iterate the spans from ssi and operate on them
|
||||
* } finally {
|
||||
* ssi.dispose();
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public static ShapeSpanIterator getFillSSI(SunGraphics2D sg2d) {
|
||||
boolean adjust = ((sg2d.stroke instanceof BasicStroke) &&
|
||||
sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);
|
||||
return new ShapeSpanIterator(adjust);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a ShapeSpanIterator ready to iterate the spans of the wide
|
||||
* outline of Shape s using the attributes of the SunGraphics2D
|
||||
* object.
|
||||
*
|
||||
* The ShapeSpanIterator returned will be fully constructed
|
||||
* and filled with the geometry from the Shape widened by the
|
||||
* appropriate BasicStroke and normalization parameters taken
|
||||
* from the SunGraphics2D object and be ready to start returning
|
||||
* spans.
|
||||
*
|
||||
* Note that the caller is responsible for calling dispose()
|
||||
* on the returned ShapeSpanIterator inside a try/finally block.
|
||||
* <pre>
|
||||
* ShapeSpanIterator ssi = LoopPipe.getStrokeSpans(sg2d, s);
|
||||
* try {
|
||||
* // iterate the spans from ssi and operate on them
|
||||
* } finally {
|
||||
* ssi.dispose();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* REMIND: This should return a SpanIterator interface object
|
||||
* but the caller needs to dispose() the object and that method
|
||||
* is only on ShapeSpanIterator.
|
||||
* TODO: Add a dispose() method to the SpanIterator interface.
|
||||
*/
|
||||
public static ShapeSpanIterator getStrokeSpans(SunGraphics2D sg2d,
|
||||
Shape s)
|
||||
{
|
||||
ShapeSpanIterator sr = new ShapeSpanIterator(false);
|
||||
|
||||
try {
|
||||
sr.setOutputArea(sg2d.getCompClip());
|
||||
sr.setRule(PathIterator.WIND_NON_ZERO);
|
||||
|
||||
BasicStroke bs = (BasicStroke) sg2d.stroke;
|
||||
boolean thin = (sg2d.strokeState <= SunGraphics2D.STROKE_THINDASHED);
|
||||
boolean normalize =
|
||||
(sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);
|
||||
|
||||
RenderEngine.strokeTo(s,
|
||||
sg2d.transform, bs,
|
||||
thin, normalize, false, sr);
|
||||
} catch (Throwable t) {
|
||||
sr.dispose();
|
||||
sr = null;
|
||||
throw new InternalError("Unable to Stroke shape ("+
|
||||
t.getMessage()+")", t);
|
||||
}
|
||||
return sr;
|
||||
}
|
||||
|
||||
public void fill(SunGraphics2D sg2d, Shape s) {
|
||||
if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {
|
||||
Path2D.Float p2df;
|
||||
int transX;
|
||||
int transY;
|
||||
if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
|
||||
if (s instanceof Path2D.Float) {
|
||||
p2df = (Path2D.Float)s;
|
||||
} else {
|
||||
p2df = new Path2D.Float(s);
|
||||
}
|
||||
transX = sg2d.transX;
|
||||
transY = sg2d.transY;
|
||||
} else {
|
||||
p2df = new Path2D.Float(s, sg2d.transform);
|
||||
transX = 0;
|
||||
transY = 0;
|
||||
}
|
||||
sg2d.loops.fillPathLoop.FillPath(sg2d, sg2d.getSurfaceData(),
|
||||
transX, transY, p2df);
|
||||
return;
|
||||
}
|
||||
|
||||
ShapeSpanIterator sr = getFillSSI(sg2d);
|
||||
try {
|
||||
sr.setOutputArea(sg2d.getCompClip());
|
||||
AffineTransform at =
|
||||
((sg2d.transformState == SunGraphics2D.TRANSFORM_ISIDENT)
|
||||
? null
|
||||
: sg2d.transform);
|
||||
sr.appendPath(s.getPathIterator(at));
|
||||
fillSpans(sg2d, sr);
|
||||
} finally {
|
||||
sr.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static void fillSpans(SunGraphics2D sg2d, SpanIterator si) {
|
||||
// REMIND: Eventually, the plan is that it will not be possible for
|
||||
// fs to be null since the FillSpans loop will be the fundamental
|
||||
// loop implemented for any destination type...
|
||||
if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {
|
||||
si = sg2d.clipRegion.filter(si);
|
||||
// REMIND: Region.filter produces a Java-only iterator
|
||||
// with no native counterpart...
|
||||
} else {
|
||||
sun.java2d.loops.FillSpans fs = sg2d.loops.fillSpansLoop;
|
||||
if (fs != null) {
|
||||
fs.FillSpans(sg2d, sg2d.getSurfaceData(), si);
|
||||
return;
|
||||
}
|
||||
}
|
||||
int spanbox[] = new int[4];
|
||||
SurfaceData sd = sg2d.getSurfaceData();
|
||||
while (si.nextSpan(spanbox)) {
|
||||
int x = spanbox[0];
|
||||
int y = spanbox[1];
|
||||
int w = spanbox[2] - x;
|
||||
int h = spanbox[3] - y;
|
||||
sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
FillParallelogram fp = sg2d.loops.fillParallelogramLoop;
|
||||
fp.FillParallelogram(sg2d, sg2d.getSurfaceData(),
|
||||
x, y, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
|
||||
public void drawParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
DrawParallelogram dp = sg2d.loops.drawParallelogramLoop;
|
||||
dp.DrawParallelogram(sg2d, sg2d.getSurfaceData(),
|
||||
x, y, dx1, dy1, dx2, dy2, lw1, lw2);
|
||||
}
|
||||
}
|
||||
155
jdkSrc/jdk8/sun/java2d/pipe/NullPipe.java
Normal file
155
jdkSrc/jdk8/sun/java2d/pipe/NullPipe.java
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2003, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Color;
|
||||
import java.awt.Image;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.font.GlyphVector;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This is a class that implements all of the basic pixel rendering
|
||||
* methods as NOPs.
|
||||
* This class is useful for installing as the pipeline when the
|
||||
* clip is determined to be empty or when the composite operation is
|
||||
* determined to have no effect (i.e. rule == SRC_OVER, extraAlpha == 0.0).
|
||||
*/
|
||||
public class NullPipe
|
||||
implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, TextPipe,
|
||||
DrawImagePipe
|
||||
{
|
||||
public void drawLine(SunGraphics2D sg,
|
||||
int x1, int y1, int x2, int y2) {
|
||||
}
|
||||
|
||||
public void drawRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height) {
|
||||
}
|
||||
|
||||
public void fillRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height) {
|
||||
}
|
||||
|
||||
public void drawRoundRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight) {
|
||||
}
|
||||
|
||||
public void fillRoundRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight) {
|
||||
}
|
||||
|
||||
public void drawOval(SunGraphics2D sg,
|
||||
int x, int y, int width, int height) {
|
||||
}
|
||||
|
||||
public void fillOval(SunGraphics2D sg,
|
||||
int x, int y, int width, int height) {
|
||||
}
|
||||
|
||||
public void drawArc(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle) {
|
||||
}
|
||||
|
||||
public void fillArc(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle) {
|
||||
}
|
||||
|
||||
public void drawPolyline(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints) {
|
||||
}
|
||||
|
||||
public void drawPolygon(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints) {
|
||||
}
|
||||
|
||||
public void fillPolygon(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints) {
|
||||
}
|
||||
|
||||
public void draw(SunGraphics2D sg, Shape s) {
|
||||
}
|
||||
|
||||
public void fill(SunGraphics2D sg, Shape s) {
|
||||
}
|
||||
|
||||
public void drawString(SunGraphics2D sg, String s, double x, double y) {
|
||||
}
|
||||
|
||||
public void drawGlyphVector(SunGraphics2D sg, GlyphVector g,
|
||||
float x, float y) {
|
||||
}
|
||||
|
||||
public void drawChars(SunGraphics2D sg,
|
||||
char data[], int offset, int length,
|
||||
int x, int y) {
|
||||
}
|
||||
|
||||
public boolean copyImage(SunGraphics2D sg, Image img,
|
||||
int x, int y,
|
||||
Color bgColor,
|
||||
ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
public boolean copyImage(SunGraphics2D sg, Image img,
|
||||
int dx, int dy, int sx, int sy, int w, int h,
|
||||
Color bgColor,
|
||||
ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
public boolean scaleImage(SunGraphics2D sg, Image img, int x, int y,
|
||||
int w, int h,
|
||||
Color bgColor,
|
||||
ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
public boolean scaleImage(SunGraphics2D sg, Image img,
|
||||
int dx1, int dy1, int dx2, int dy2,
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
Color bgColor,
|
||||
ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
public boolean transformImage(SunGraphics2D sg, Image img,
|
||||
AffineTransform atfm,
|
||||
ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
public void transformImage(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp op, int x, int y) {
|
||||
}
|
||||
}
|
||||
145
jdkSrc/jdk8/sun/java2d/pipe/OutlineTextRenderer.java
Normal file
145
jdkSrc/jdk8/sun/java2d/pipe/OutlineTextRenderer.java
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2005, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.TextLayout;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.font.GlyphList;
|
||||
import sun.awt.SunHints;
|
||||
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.font.TextLayout;
|
||||
|
||||
/**
|
||||
* A delegate pipe of SG2D for drawing "large" text with
|
||||
* a solid source colour to an opaque destination.
|
||||
* The text is drawn as a filled outline.
|
||||
* Since the developer is not explicitly requesting this way of
|
||||
* rendering, this should not be used if the current paint is not
|
||||
* a solid colour.
|
||||
*
|
||||
* If text anti-aliasing is requested by the application, and
|
||||
* filling path, an anti-aliasing fill pipe needs to
|
||||
* be invoked.
|
||||
* This involves making some of the same decisions as in the
|
||||
* validatePipe call, which may be in a SurfaceData subclass, so
|
||||
* its awkward to always ensure that the correct pipe is used.
|
||||
* The easiest thing, rather than reproducing much of that logic
|
||||
* is to call validatePipe() which works but is expensive, although
|
||||
* probably not compared to the cost of filling the path.
|
||||
* Note if AA hint is ON but text-AA hint is OFF this logic will
|
||||
* produce AA text which perhaps isn't what the user expected.
|
||||
* Note that the glyphvector obeys its FRC, not the G2D.
|
||||
*/
|
||||
|
||||
public class OutlineTextRenderer implements TextPipe {
|
||||
|
||||
// Text with a height greater than the threshhold will be
|
||||
// drawn via this pipe.
|
||||
public static final int THRESHHOLD = 100;
|
||||
|
||||
public void drawChars(SunGraphics2D g2d,
|
||||
char data[], int offset, int length,
|
||||
int x, int y) {
|
||||
|
||||
String s = new String(data, offset, length);
|
||||
drawString(g2d, s, x, y);
|
||||
}
|
||||
|
||||
public void drawString(SunGraphics2D g2d, String str, double x, double y) {
|
||||
|
||||
if ("".equals(str)) {
|
||||
return; // TextLayout constructor throws IAE on "".
|
||||
}
|
||||
TextLayout tl = new TextLayout(str, g2d.getFont(),
|
||||
g2d.getFontRenderContext());
|
||||
Shape s = tl.getOutline(AffineTransform.getTranslateInstance(x, y));
|
||||
|
||||
int textAAHint = g2d.getFontInfo().aaHint;
|
||||
|
||||
int prevaaHint = - 1;
|
||||
if (textAAHint != SunHints.INTVAL_TEXT_ANTIALIAS_OFF &&
|
||||
g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
|
||||
prevaaHint = g2d.antialiasHint;
|
||||
g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_ON;
|
||||
g2d.validatePipe();
|
||||
} else if (textAAHint == SunHints.INTVAL_TEXT_ANTIALIAS_OFF
|
||||
&& g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_OFF) {
|
||||
prevaaHint = g2d.antialiasHint;
|
||||
g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF;
|
||||
g2d.validatePipe();
|
||||
}
|
||||
|
||||
g2d.fill(s);
|
||||
|
||||
if (prevaaHint != -1) {
|
||||
g2d.antialiasHint = prevaaHint;
|
||||
g2d.validatePipe();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawGlyphVector(SunGraphics2D g2d, GlyphVector gv,
|
||||
float x, float y) {
|
||||
|
||||
|
||||
Shape s = gv.getOutline(x, y);
|
||||
int prevaaHint = - 1;
|
||||
FontRenderContext frc = gv.getFontRenderContext();
|
||||
boolean aa = frc.isAntiAliased();
|
||||
|
||||
/* aa will be true if any AA mode has been specified.
|
||||
* ie for LCD and 'gasp' modes too.
|
||||
* We will check if 'gasp' has resolved AA to be "OFF", and
|
||||
* in all other cases (ie AA ON and all LCD modes) use AA outlines.
|
||||
*/
|
||||
if (aa) {
|
||||
if (g2d.getGVFontInfo(gv.getFont(), frc).aaHint ==
|
||||
SunHints.INTVAL_TEXT_ANTIALIAS_OFF) {
|
||||
aa = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (aa && g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
|
||||
prevaaHint = g2d.antialiasHint;
|
||||
g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_ON;
|
||||
g2d.validatePipe();
|
||||
} else if (!aa && g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_OFF) {
|
||||
prevaaHint = g2d.antialiasHint;
|
||||
g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF;
|
||||
g2d.validatePipe();
|
||||
}
|
||||
|
||||
g2d.fill(s);
|
||||
|
||||
if (prevaaHint != -1) {
|
||||
g2d.antialiasHint = prevaaHint;
|
||||
g2d.validatePipe();
|
||||
}
|
||||
}
|
||||
}
|
||||
76
jdkSrc/jdk8/sun/java2d/pipe/ParallelogramPipe.java
Normal file
76
jdkSrc/jdk8/sun/java2d/pipe/ParallelogramPipe.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2012, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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 sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This interface defines the set of calls that pipeline objects
|
||||
* can use to pass on responsibility for drawing arbitrary
|
||||
* parallelogram shapes.
|
||||
* Six floating point numbers are provided and the parallelogram
|
||||
* is defined as the quadrilateral with the following vertices:
|
||||
* <pre>
|
||||
* origin: (x, y)
|
||||
* => (x+dx1, y+dy1)
|
||||
* => (x+dx1+dx2, y+dy1+dy2)
|
||||
* => (x+dx2, y+dy2)
|
||||
* => origin
|
||||
* </pre>
|
||||
* The four u[xy][12] parameters are the unsorted extreme coordinates
|
||||
* of the primitive in user space. They may have been generated by a
|
||||
* line or a rectangle so they could have u[xy]2 < u[xy]1 in some cases.
|
||||
* They should be sorted before calculating the bounds of the original
|
||||
* primitive (such as for calculating the user space bounds for the
|
||||
* Paint.createContext() method).
|
||||
*/
|
||||
public interface ParallelogramPipe {
|
||||
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);
|
||||
|
||||
/**
|
||||
* Draw a Parallelogram with the indicated line widths
|
||||
* assuming a standard BasicStroke with MITER joins.
|
||||
* lw1 specifies the width of the stroke along the dx1,dy1
|
||||
* vector and lw2 specifies the width of the stroke along
|
||||
* the dx2,dy2 vector.
|
||||
* This is equivalent to outsetting the indicated
|
||||
* parallelogram by lw/2 pixels, then insetting the
|
||||
* same parallelogram by lw/2 pixels and filling the
|
||||
* difference between the outer and inner parallelograms.
|
||||
*/
|
||||
public void drawParallelogram(SunGraphics2D sg,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2);
|
||||
}
|
||||
67
jdkSrc/jdk8/sun/java2d/pipe/PixelDrawPipe.java
Normal file
67
jdkSrc/jdk8/sun/java2d/pipe/PixelDrawPipe.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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 sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This interface defines the set of calls that pipeline objects
|
||||
* can use to pass on responsibility for drawing various basic
|
||||
* geometric figures defined by explicit integer coordinates.
|
||||
* Typically this interface will be used for communication when
|
||||
* the coordinates of the rendering have been narrowed down to
|
||||
* actual device pixels, or for communication of untransformed
|
||||
* coordinates when the coordinates were specified using integers.
|
||||
* This interface does not cover all of the rendering calls that
|
||||
* are possible in Graphics since many of the rendering calls can
|
||||
* be transformed into one or more variants of these calls.
|
||||
*/
|
||||
public interface PixelDrawPipe {
|
||||
public void drawLine(SunGraphics2D sg,
|
||||
int x1, int y1, int x2, int y2);
|
||||
|
||||
public void drawRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
public void drawRoundRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight);
|
||||
|
||||
public void drawOval(SunGraphics2D sg,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
public void drawArc(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle);
|
||||
|
||||
public void drawPolyline(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints);
|
||||
|
||||
public void drawPolygon(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints);
|
||||
}
|
||||
61
jdkSrc/jdk8/sun/java2d/pipe/PixelFillPipe.java
Normal file
61
jdkSrc/jdk8/sun/java2d/pipe/PixelFillPipe.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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 sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This interface defines the set of calls that pipeline objects
|
||||
* can use to pass on responsibility for filling various basic
|
||||
* geometric figures defined by explicit integer coordinates.
|
||||
* Typically this interface will be used for communication when
|
||||
* the coordinates of the rendering have been narrowed down to
|
||||
* actual device pixels, or for communication of untransformed
|
||||
* coordinates when the coordinates were specified using integers.
|
||||
* This interface does not cover all of the rendering calls that
|
||||
* are possible in Graphics since many of the rendering calls can
|
||||
* be transformed into one or more variants of these calls.
|
||||
*/
|
||||
public interface PixelFillPipe {
|
||||
public void fillRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
|
||||
public void fillRoundRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight);
|
||||
|
||||
public void fillOval(SunGraphics2D sg,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
public void fillArc(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle);
|
||||
|
||||
public void fillPolygon(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints);
|
||||
}
|
||||
429
jdkSrc/jdk8/sun/java2d/pipe/PixelToParallelogramConverter.java
Normal file
429
jdkSrc/jdk8/sun/java2d/pipe/PixelToParallelogramConverter.java
Normal file
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Shape;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.awt.SunHints;
|
||||
|
||||
/**
|
||||
* This class converts calls to the basic pixel rendering methods
|
||||
* into calls to the methods on a ParallelogramPipe.
|
||||
* Most calls are transformed into calls to the fill(Shape) method
|
||||
* by the parent PixelToShapeConverter class, but some calls are
|
||||
* transformed into calls to fill/drawParallelogram().
|
||||
*/
|
||||
public class PixelToParallelogramConverter extends PixelToShapeConverter
|
||||
implements ShapeDrawPipe
|
||||
{
|
||||
ParallelogramPipe outrenderer;
|
||||
double minPenSize;
|
||||
double normPosition;
|
||||
double normRoundingBias;
|
||||
boolean adjustfill;
|
||||
|
||||
/**
|
||||
* @param shapepipe pipeline to forward shape calls to
|
||||
* @param pgrampipe pipeline to forward parallelogram calls to
|
||||
* (and drawLine calls if possible)
|
||||
* @param minPenSize minimum pen size for dropout control
|
||||
* @param normPosition sub-pixel location to normalize endpoints
|
||||
* for STROKE_NORMALIZE cases
|
||||
* @param adjustFill boolean to control whethere normalization
|
||||
* constants are also applied to fill operations
|
||||
* (normally true for non-AA, false for AA)
|
||||
*/
|
||||
public PixelToParallelogramConverter(ShapeDrawPipe shapepipe,
|
||||
ParallelogramPipe pgrampipe,
|
||||
double minPenSize,
|
||||
double normPosition,
|
||||
boolean adjustfill)
|
||||
{
|
||||
super(shapepipe);
|
||||
outrenderer = pgrampipe;
|
||||
this.minPenSize = minPenSize;
|
||||
this.normPosition = normPosition;
|
||||
this.normRoundingBias = 0.5 - normPosition;
|
||||
this.adjustfill = adjustfill;
|
||||
}
|
||||
|
||||
public void drawLine(SunGraphics2D sg2d,
|
||||
int x1, int y1, int x2, int y2)
|
||||
{
|
||||
if (!drawGeneralLine(sg2d, x1, y1, x2, y2)) {
|
||||
super.drawLine(sg2d, x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawRect(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
if (w >= 0 && h >= 0) {
|
||||
if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
|
||||
BasicStroke bs = ((BasicStroke) sg2d.stroke);
|
||||
if (w > 0 && h > 0) {
|
||||
if (bs.getLineJoin() == BasicStroke.JOIN_MITER &&
|
||||
bs.getDashArray() == null)
|
||||
{
|
||||
double lw = bs.getLineWidth();
|
||||
drawRectangle(sg2d, x, y, w, h, lw);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Note: This calls the integer version which
|
||||
// will verify that the local drawLine optimizations
|
||||
// work and call super.drawLine(), if not.
|
||||
drawLine(sg2d, x, y, x+w, y+h);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.drawRect(sg2d, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillRect(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
if (w > 0 && h > 0) {
|
||||
fillRectangle(sg2d, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(SunGraphics2D sg2d, Shape s) {
|
||||
if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
|
||||
BasicStroke bs = ((BasicStroke) sg2d.stroke);
|
||||
if (s instanceof Rectangle2D) {
|
||||
if (bs.getLineJoin() == BasicStroke.JOIN_MITER &&
|
||||
bs.getDashArray() == null)
|
||||
{
|
||||
Rectangle2D r2d = (Rectangle2D) s;
|
||||
double w = r2d.getWidth();
|
||||
double h = r2d.getHeight();
|
||||
double x = r2d.getX();
|
||||
double y = r2d.getY();
|
||||
if (w >= 0 && h >= 0) {
|
||||
double lw = bs.getLineWidth();
|
||||
drawRectangle(sg2d, x, y, w, h, lw);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (s instanceof Line2D) {
|
||||
Line2D l2d = (Line2D) s;
|
||||
if (drawGeneralLine(sg2d,
|
||||
l2d.getX1(), l2d.getY1(),
|
||||
l2d.getX2(), l2d.getY2()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outpipe.draw(sg2d, s);
|
||||
}
|
||||
|
||||
public void fill(SunGraphics2D sg2d, Shape s) {
|
||||
if (s instanceof Rectangle2D) {
|
||||
Rectangle2D r2d = (Rectangle2D) s;
|
||||
double w = r2d.getWidth();
|
||||
double h = r2d.getHeight();
|
||||
if (w > 0 && h > 0) {
|
||||
double x = r2d.getX();
|
||||
double y = r2d.getY();
|
||||
fillRectangle(sg2d, x, y, w, h);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
outpipe.fill(sg2d, s);
|
||||
}
|
||||
|
||||
static double len(double x, double y) {
|
||||
return ((x == 0) ? Math.abs(y)
|
||||
: ((y == 0) ? Math.abs(x)
|
||||
: Math.sqrt(x * x + y * y)));
|
||||
}
|
||||
|
||||
double normalize(double v) {
|
||||
return Math.floor(v + normRoundingBias) + normPosition;
|
||||
}
|
||||
|
||||
public boolean drawGeneralLine(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2)
|
||||
{
|
||||
if (sg2d.strokeState == SunGraphics2D.STROKE_CUSTOM ||
|
||||
sg2d.strokeState == SunGraphics2D.STROKE_THINDASHED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
BasicStroke bs = (BasicStroke) sg2d.stroke;
|
||||
int cap = bs.getEndCap();
|
||||
if (cap == BasicStroke.CAP_ROUND || bs.getDashArray() != null) {
|
||||
// TODO: we could construct the GeneralPath directly
|
||||
// for CAP_ROUND and save a lot of processing in that case...
|
||||
// And again, we would need to deal with dropout control...
|
||||
return false;
|
||||
}
|
||||
double lw = bs.getLineWidth();
|
||||
// Save the original dx, dy in case we need it to transform
|
||||
// the linewidth as a perpendicular vector below
|
||||
double dx = ux2 - ux1;
|
||||
double dy = uy2 - uy1;
|
||||
double x1, y1, x2, y2;
|
||||
switch (sg2d.transformState) {
|
||||
case SunGraphics2D.TRANSFORM_GENERIC:
|
||||
case SunGraphics2D.TRANSFORM_TRANSLATESCALE:
|
||||
{
|
||||
double coords[] = {ux1, uy1, ux2, uy2};
|
||||
sg2d.transform.transform(coords, 0, coords, 0, 2);
|
||||
x1 = coords[0];
|
||||
y1 = coords[1];
|
||||
x2 = coords[2];
|
||||
y2 = coords[3];
|
||||
}
|
||||
break;
|
||||
case SunGraphics2D.TRANSFORM_ANY_TRANSLATE:
|
||||
case SunGraphics2D.TRANSFORM_INT_TRANSLATE:
|
||||
{
|
||||
double tx = sg2d.transform.getTranslateX();
|
||||
double ty = sg2d.transform.getTranslateY();
|
||||
x1 = ux1 + tx;
|
||||
y1 = uy1 + ty;
|
||||
x2 = ux2 + tx;
|
||||
y2 = uy2 + ty;
|
||||
}
|
||||
break;
|
||||
case SunGraphics2D.TRANSFORM_ISIDENT:
|
||||
x1 = ux1;
|
||||
y1 = uy1;
|
||||
x2 = ux2;
|
||||
y2 = uy2;
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("unknown TRANSFORM state...");
|
||||
}
|
||||
if (sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE) {
|
||||
if (sg2d.strokeState == SunGraphics2D.STROKE_THIN &&
|
||||
outrenderer instanceof PixelDrawPipe)
|
||||
{
|
||||
// PixelDrawPipes will add sg2d.transXY so we need to factor
|
||||
// that out...
|
||||
int ix1 = (int) Math.floor(x1 - sg2d.transX);
|
||||
int iy1 = (int) Math.floor(y1 - sg2d.transY);
|
||||
int ix2 = (int) Math.floor(x2 - sg2d.transX);
|
||||
int iy2 = (int) Math.floor(y2 - sg2d.transY);
|
||||
((PixelDrawPipe)outrenderer).drawLine(sg2d, ix1, iy1, ix2, iy2);
|
||||
return true;
|
||||
}
|
||||
x1 = normalize(x1);
|
||||
y1 = normalize(y1);
|
||||
x2 = normalize(x2);
|
||||
y2 = normalize(y2);
|
||||
}
|
||||
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
|
||||
// Transform the linewidth...
|
||||
// calculate the scaling factor for a unit vector
|
||||
// perpendicular to the original user space line.
|
||||
double len = len(dx, dy);
|
||||
if (len == 0) {
|
||||
dx = len = 1;
|
||||
// dy = 0; already
|
||||
}
|
||||
// delta transform the transposed (90 degree rotated) unit vector
|
||||
double unitvector[] = {dy/len, -dx/len};
|
||||
sg2d.transform.deltaTransform(unitvector, 0, unitvector, 0, 1);
|
||||
lw *= len(unitvector[0], unitvector[1]);
|
||||
}
|
||||
lw = Math.max(lw, minPenSize);
|
||||
dx = x2 - x1;
|
||||
dy = y2 - y1;
|
||||
double len = len(dx, dy);
|
||||
double udx, udy;
|
||||
if (len == 0) {
|
||||
if (cap == BasicStroke.CAP_BUTT) {
|
||||
return true;
|
||||
}
|
||||
udx = lw;
|
||||
udy = 0;
|
||||
} else {
|
||||
udx = lw * dx / len;
|
||||
udy = lw * dy / len;
|
||||
}
|
||||
double px = x1 + udy / 2.0;
|
||||
double py = y1 - udx / 2.0;
|
||||
if (cap == BasicStroke.CAP_SQUARE) {
|
||||
px -= udx / 2.0;
|
||||
py -= udy / 2.0;
|
||||
dx += udx;
|
||||
dy += udy;
|
||||
}
|
||||
outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
|
||||
px, py, -udy, udx, dx, dy);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void fillRectangle(SunGraphics2D sg2d,
|
||||
double rx, double ry,
|
||||
double rw, double rh)
|
||||
{
|
||||
double px, py;
|
||||
double dx1, dy1, dx2, dy2;
|
||||
AffineTransform txform = sg2d.transform;
|
||||
dx1 = txform.getScaleX();
|
||||
dy1 = txform.getShearY();
|
||||
dx2 = txform.getShearX();
|
||||
dy2 = txform.getScaleY();
|
||||
px = rx * dx1 + ry * dx2 + txform.getTranslateX();
|
||||
py = rx * dy1 + ry * dy2 + txform.getTranslateY();
|
||||
dx1 *= rw;
|
||||
dy1 *= rw;
|
||||
dx2 *= rh;
|
||||
dy2 *= rh;
|
||||
if (adjustfill &&
|
||||
sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM &&
|
||||
sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE)
|
||||
{
|
||||
double newx = normalize(px);
|
||||
double newy = normalize(py);
|
||||
dx1 = normalize(px + dx1) - newx;
|
||||
dy1 = normalize(py + dy1) - newy;
|
||||
dx2 = normalize(px + dx2) - newx;
|
||||
dy2 = normalize(py + dy2) - newy;
|
||||
px = newx;
|
||||
py = newy;
|
||||
}
|
||||
outrenderer.fillParallelogram(sg2d, rx, ry, rx+rw, ry+rh,
|
||||
px, py, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
|
||||
public void drawRectangle(SunGraphics2D sg2d,
|
||||
double rx, double ry,
|
||||
double rw, double rh,
|
||||
double lw)
|
||||
{
|
||||
double px, py;
|
||||
double dx1, dy1, dx2, dy2;
|
||||
double lw1, lw2;
|
||||
AffineTransform txform = sg2d.transform;
|
||||
dx1 = txform.getScaleX();
|
||||
dy1 = txform.getShearY();
|
||||
dx2 = txform.getShearX();
|
||||
dy2 = txform.getScaleY();
|
||||
px = rx * dx1 + ry * dx2 + txform.getTranslateX();
|
||||
py = rx * dy1 + ry * dy2 + txform.getTranslateY();
|
||||
// lw along dx1,dy1 scale by transformed length of dx2,dy2 vectors
|
||||
// and vice versa
|
||||
lw1 = len(dx1, dy1) * lw;
|
||||
lw2 = len(dx2, dy2) * lw;
|
||||
dx1 *= rw;
|
||||
dy1 *= rw;
|
||||
dx2 *= rh;
|
||||
dy2 *= rh;
|
||||
if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM &&
|
||||
sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE)
|
||||
{
|
||||
double newx = normalize(px);
|
||||
double newy = normalize(py);
|
||||
dx1 = normalize(px + dx1) - newx;
|
||||
dy1 = normalize(py + dy1) - newy;
|
||||
dx2 = normalize(px + dx2) - newx;
|
||||
dy2 = normalize(py + dy2) - newy;
|
||||
px = newx;
|
||||
py = newy;
|
||||
}
|
||||
lw1 = Math.max(lw1, minPenSize);
|
||||
lw2 = Math.max(lw2, minPenSize);
|
||||
double len1 = len(dx1, dy1);
|
||||
double len2 = len(dx2, dy2);
|
||||
if (lw1 >= len1 || lw2 >= len2) {
|
||||
// The line widths are large enough to consume the
|
||||
// entire hole in the middle of the parallelogram
|
||||
// so we can just fill the outer parallelogram.
|
||||
fillOuterParallelogram(sg2d,
|
||||
rx, ry, rx+rw, ry+rh,
|
||||
px, py, dx1, dy1, dx2, dy2,
|
||||
len1, len2, lw1, lw2);
|
||||
} else {
|
||||
outrenderer.drawParallelogram(sg2d,
|
||||
rx, ry, rx+rw, ry+rh,
|
||||
px, py, dx1, dy1, dx2, dy2,
|
||||
lw1 / len1, lw2 / len2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This utility function handles the case where a drawRectangle
|
||||
* operation discovered that the interior hole in the rectangle
|
||||
* or parallelogram has been completely filled in by the stroke
|
||||
* width. It calculates the outer parallelogram of the stroke
|
||||
* and issues a single fillParallelogram request to fill it.
|
||||
*/
|
||||
public void fillOuterParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double px, double py,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double len1, double len2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
double udx1 = dx1 / len1;
|
||||
double udy1 = dy1 / len1;
|
||||
double udx2 = dx2 / len2;
|
||||
double udy2 = dy2 / len2;
|
||||
if (len1 == 0) {
|
||||
// len1 is 0, replace udxy1 with perpendicular of udxy2
|
||||
if (len2 == 0) {
|
||||
// both are 0, use a unit Y vector for udxy2
|
||||
udx2 = 0;
|
||||
udy2 = 1;
|
||||
}
|
||||
udx1 = udy2;
|
||||
udy1 = -udx2;
|
||||
} else if (len2 == 0) {
|
||||
// len2 is 0, replace udxy2 with perpendicular of udxy1
|
||||
udx2 = udy1;
|
||||
udy2 = -udx1;
|
||||
}
|
||||
udx1 *= lw1;
|
||||
udy1 *= lw1;
|
||||
udx2 *= lw2;
|
||||
udy2 *= lw2;
|
||||
px -= (udx1 + udx2) / 2;
|
||||
py -= (udy1 + udy2) / 2;
|
||||
dx1 += udx1;
|
||||
dy1 += udy1;
|
||||
dx2 += udx2;
|
||||
dy2 += udy2;
|
||||
|
||||
outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
|
||||
px, py, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
}
|
||||
133
jdkSrc/jdk8/sun/java2d/pipe/PixelToShapeConverter.java
Normal file
133
jdkSrc/jdk8/sun/java2d/pipe/PixelToShapeConverter.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Arc2D;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This class converts calls to the basic pixel rendering methods
|
||||
* into calls to a generic Shape rendering pipeline.
|
||||
*/
|
||||
public class PixelToShapeConverter
|
||||
implements PixelDrawPipe, PixelFillPipe
|
||||
{
|
||||
ShapeDrawPipe outpipe;
|
||||
|
||||
public PixelToShapeConverter(ShapeDrawPipe pipe) {
|
||||
outpipe = pipe;
|
||||
}
|
||||
|
||||
public void drawLine(SunGraphics2D sg,
|
||||
int x1, int y1, int x2, int y2) {
|
||||
outpipe.draw(sg, new Line2D.Float(x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
public void drawRect(SunGraphics2D sg,
|
||||
int x, int y, int w, int h) {
|
||||
outpipe.draw(sg, new Rectangle(x, y, w, h));
|
||||
}
|
||||
|
||||
public void fillRect(SunGraphics2D sg,
|
||||
int x, int y, int w, int h) {
|
||||
outpipe.fill(sg, new Rectangle(x, y, w, h));
|
||||
}
|
||||
|
||||
public void drawRoundRect(SunGraphics2D sg,
|
||||
int x, int y, int w, int h,
|
||||
int aW, int aH) {
|
||||
outpipe.draw(sg, new RoundRectangle2D.Float(x, y, w, h, aW, aH));
|
||||
}
|
||||
|
||||
public void fillRoundRect(SunGraphics2D sg,
|
||||
int x, int y, int w, int h,
|
||||
int aW, int aH) {
|
||||
outpipe.fill(sg, new RoundRectangle2D.Float(x, y, w, h, aW, aH));
|
||||
}
|
||||
|
||||
public void drawOval(SunGraphics2D sg,
|
||||
int x, int y, int w, int h) {
|
||||
outpipe.draw(sg, new Ellipse2D.Float(x, y, w, h));
|
||||
}
|
||||
|
||||
public void fillOval(SunGraphics2D sg,
|
||||
int x, int y, int w, int h) {
|
||||
outpipe.fill(sg, new Ellipse2D.Float(x, y, w, h));
|
||||
}
|
||||
|
||||
public void drawArc(SunGraphics2D sg,
|
||||
int x, int y, int w, int h,
|
||||
int start, int extent) {
|
||||
outpipe.draw(sg, new Arc2D.Float(x, y, w, h,
|
||||
start, extent, Arc2D.OPEN));
|
||||
}
|
||||
|
||||
public void fillArc(SunGraphics2D sg,
|
||||
int x, int y, int w, int h,
|
||||
int start, int extent) {
|
||||
outpipe.fill(sg, new Arc2D.Float(x, y, w, h,
|
||||
start, extent, Arc2D.PIE));
|
||||
}
|
||||
|
||||
private Shape makePoly(int xPoints[], int yPoints[],
|
||||
int nPoints, boolean close) {
|
||||
GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
|
||||
if (nPoints > 0) {
|
||||
gp.moveTo(xPoints[0], yPoints[0]);
|
||||
for (int i = 1; i < nPoints; i++) {
|
||||
gp.lineTo(xPoints[i], yPoints[i]);
|
||||
}
|
||||
if (close) {
|
||||
gp.closePath();
|
||||
}
|
||||
}
|
||||
return gp;
|
||||
}
|
||||
|
||||
public void drawPolyline(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints) {
|
||||
outpipe.draw(sg, makePoly(xPoints, yPoints, nPoints, false));
|
||||
}
|
||||
|
||||
public void drawPolygon(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints) {
|
||||
outpipe.draw(sg, makePoly(xPoints, yPoints, nPoints, true));
|
||||
}
|
||||
|
||||
public void fillPolygon(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints) {
|
||||
outpipe.fill(sg, makePoly(xPoints, yPoints, nPoints, true));
|
||||
}
|
||||
}
|
||||
1399
jdkSrc/jdk8/sun/java2d/pipe/Region.java
Normal file
1399
jdkSrc/jdk8/sun/java2d/pipe/Region.java
Normal file
File diff suppressed because it is too large
Load Diff
392
jdkSrc/jdk8/sun/java2d/pipe/RegionClipSpanIterator.java
Normal file
392
jdkSrc/jdk8/sun/java2d/pipe/RegionClipSpanIterator.java
Normal file
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.geom.PathIterator;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
/**
|
||||
* This class clips a SpanIterator to a Region and outputs the
|
||||
* resulting spans as another SpanIterator.
|
||||
*
|
||||
* Spans are output in the usual y/x order, unless the input span
|
||||
* iterator doesn't conform to this order, or the iterator's span
|
||||
* straddle more than one band of the Region used for clipping.
|
||||
*
|
||||
* Principle of operation:
|
||||
*
|
||||
* The iterator maintains a several cursors onto the RegionIterator
|
||||
* in order to avoid having to buffer spans from the SpanIterator.
|
||||
* They are:
|
||||
* resetState The initial state of the RegionIterator
|
||||
* lwm Low Water Mark, a running start point for
|
||||
* processing each band. Usually goes down, but
|
||||
* can be reset to resetState if a span has a lower
|
||||
* start coordinate than the previous one.
|
||||
* row The start of the current band of the RegionIterator
|
||||
* box The current span of the current row
|
||||
*
|
||||
* The main nextSpan() loop implements a coroutine like structure, with
|
||||
* three producers to get the next span, row and box calling each other
|
||||
* to iterate through the span iterator and region.
|
||||
*
|
||||
* REMIND: Needs a native implementation!
|
||||
*/
|
||||
public class RegionClipSpanIterator implements SpanIterator {
|
||||
|
||||
// The inputs to the filter
|
||||
Region rgn;
|
||||
SpanIterator spanIter;
|
||||
|
||||
// The cursors that track the progress through the region
|
||||
RegionIterator resetState;
|
||||
RegionIterator lwm;
|
||||
RegionIterator row;
|
||||
RegionIterator box;
|
||||
|
||||
// The bounds of the current span iterator span
|
||||
int spanlox, spanhix, spanloy, spanhiy;
|
||||
|
||||
// The extent of the region band marking the low water mark
|
||||
int lwmloy, lwmhiy;
|
||||
|
||||
// The bounds of the current region box
|
||||
int rgnlox, rgnloy, rgnhix, rgnhiy;
|
||||
|
||||
// The bounding box of the input Region. Used for click
|
||||
// rejection of iterator spans
|
||||
int rgnbndslox, rgnbndsloy, rgnbndshix, rgnbndshiy;
|
||||
|
||||
// The array used to hold coordinates from the region iterator
|
||||
int rgnbox[] = new int[4];
|
||||
|
||||
// The array used to hold coordinates from the span iterator
|
||||
int spanbox[] = new int[4];
|
||||
|
||||
// True if the next iterator span should be read on the next
|
||||
// iteration of the main nextSpan() loop
|
||||
boolean doNextSpan;
|
||||
|
||||
// True if the next region box should be read on the next
|
||||
// iteration of the main nextSpan() loop
|
||||
boolean doNextBox;
|
||||
|
||||
// True if there are no more spans or the Region is empty
|
||||
boolean done = false;
|
||||
|
||||
/*
|
||||
* Creates an instance that filters the spans generated by
|
||||
* spanIter through the region described by rgn.
|
||||
*/
|
||||
public RegionClipSpanIterator(Region rgn, SpanIterator spanIter) {
|
||||
|
||||
this.spanIter = spanIter;
|
||||
|
||||
resetState = rgn.getIterator();
|
||||
lwm = resetState.createCopy();
|
||||
|
||||
if (!lwm.nextYRange(rgnbox)) {
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
rgnloy = lwmloy = rgnbox[1];
|
||||
rgnhiy = lwmhiy = rgnbox[3];
|
||||
|
||||
rgn.getBounds(rgnbox);
|
||||
rgnbndslox = rgnbox[0];
|
||||
rgnbndsloy = rgnbox[1];
|
||||
rgnbndshix = rgnbox[2];
|
||||
rgnbndshiy = rgnbox[3];
|
||||
if (rgnbndslox >= rgnbndshix ||
|
||||
rgnbndsloy >= rgnbndshiy) {
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.rgn = rgn;
|
||||
|
||||
|
||||
row = lwm.createCopy();
|
||||
box = row.createCopy();
|
||||
doNextSpan = true;
|
||||
doNextBox = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the bbox of the available path segments, clipped to the
|
||||
* Region.
|
||||
*/
|
||||
public void getPathBox(int pathbox[]) {
|
||||
int[] rgnbox = new int[4];
|
||||
rgn.getBounds(rgnbox);
|
||||
spanIter.getPathBox(pathbox);
|
||||
|
||||
if (pathbox[0] < rgnbox[0]) {
|
||||
pathbox[0] = rgnbox[0];
|
||||
}
|
||||
|
||||
if (pathbox[1] < rgnbox[1]) {
|
||||
pathbox[1] = rgnbox[1];
|
||||
}
|
||||
|
||||
if (pathbox[2] > rgnbox[2]) {
|
||||
pathbox[2] = rgnbox[2];
|
||||
}
|
||||
|
||||
if (pathbox[3] > rgnbox[3]) {
|
||||
pathbox[3] = rgnbox[3];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Intersects the path box with the given bbox.
|
||||
* Returned spans are clipped to this region, or discarded
|
||||
* altogether if they lie outside it.
|
||||
*/
|
||||
public void intersectClipBox(int lox, int loy, int hix, int hiy) {
|
||||
spanIter.intersectClipBox(lox, loy, hix, hiy);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fetches the next span that needs to be operated on.
|
||||
* If the return value is false then there are no more spans.
|
||||
*/
|
||||
public boolean nextSpan(int resultbox[]) {
|
||||
if (done) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int resultlox, resultloy, resulthix, resulthiy;
|
||||
boolean doNextRow = false;
|
||||
|
||||
// REMIND: Cache the coordinate inst vars used in this loop
|
||||
// in locals vars.
|
||||
while (true) {
|
||||
// We've exhausted the current span so get the next one
|
||||
if (doNextSpan) {
|
||||
if (!spanIter.nextSpan(spanbox)) {
|
||||
done = true;
|
||||
return false;
|
||||
} else {
|
||||
spanlox = spanbox[0];
|
||||
// Clip out spans that lie outside of the rgn's bounds
|
||||
if (spanlox >= rgnbndshix) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spanloy = spanbox[1];
|
||||
if (spanloy >= rgnbndshiy) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spanhix = spanbox[2];
|
||||
if (spanhix <= rgnbndslox) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spanhiy = spanbox[3];
|
||||
if (spanhiy <= rgnbndsloy) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// If the span starts higher up than the low-water mark,
|
||||
// reset the lwm. This can only happen if spans aren't
|
||||
// returned in strict y/x order, or the first time through.
|
||||
if (lwmloy > spanloy) {
|
||||
lwm.copyStateFrom(resetState);
|
||||
lwm.nextYRange(rgnbox);
|
||||
lwmloy = rgnbox[1];
|
||||
lwmhiy = rgnbox[3];
|
||||
}
|
||||
// Skip to the first rgn row whose bottom edge is
|
||||
// below the top of the current span. This will only
|
||||
// execute >0 times when the current span starts in a
|
||||
// lower region row than the previous one, or possibly the
|
||||
// first time through.
|
||||
while (lwmhiy <= spanloy) {
|
||||
if (!lwm.nextYRange(rgnbox))
|
||||
break;
|
||||
lwmloy = rgnbox[1];
|
||||
lwmhiy = rgnbox[3];
|
||||
}
|
||||
// If the row overlaps the span, process it, otherwise
|
||||
// fetch another span
|
||||
if (lwmhiy > spanloy && lwmloy < spanhiy) {
|
||||
// Update the current row if it's different from the
|
||||
// new lwm
|
||||
if (rgnloy != lwmloy) {
|
||||
row.copyStateFrom(lwm);
|
||||
rgnloy = lwmloy;
|
||||
rgnhiy = lwmhiy;
|
||||
}
|
||||
box.copyStateFrom(row);
|
||||
doNextBox = true;
|
||||
doNextSpan = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// The current row's spans are exhausted, do the next one
|
||||
if (doNextRow) {
|
||||
// Next time we either do the next span or the next box
|
||||
doNextRow = false;
|
||||
// Get the next row
|
||||
boolean ok = row.nextYRange(rgnbox);
|
||||
// If there was one, update the bounds
|
||||
if (ok) {
|
||||
rgnloy = rgnbox[1];
|
||||
rgnhiy = rgnbox[3];
|
||||
}
|
||||
if (!ok || rgnloy >= spanhiy) {
|
||||
// If we've exhausted the rows or this one is below the span,
|
||||
// go onto the next span
|
||||
doNextSpan = true;
|
||||
}
|
||||
else {
|
||||
// Otherwise get the first box on this row
|
||||
box.copyStateFrom(row);
|
||||
doNextBox = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Process the next box in the current row
|
||||
if (doNextBox) {
|
||||
boolean ok = box.nextXBand(rgnbox);
|
||||
if (ok) {
|
||||
rgnlox = rgnbox[0];
|
||||
rgnhix = rgnbox[2];
|
||||
}
|
||||
if (!ok || rgnlox >= spanhix) {
|
||||
// If there was no next rgn span or it's beyond the
|
||||
// source span, go onto the next row or span
|
||||
doNextBox = false;
|
||||
if (rgnhiy >= spanhiy) {
|
||||
// If the current row totally overlaps the span,
|
||||
// go onto the next span
|
||||
doNextSpan = true;
|
||||
} else {
|
||||
// otherwise go onto the next rgn row
|
||||
doNextRow = true;
|
||||
}
|
||||
} else {
|
||||
// Otherwise, if the new rgn span overlaps the
|
||||
// spanbox, no need to get another box
|
||||
doNextBox = rgnhix <= spanlox;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prepare to do the next box either on this call or
|
||||
// or the subsequent one
|
||||
doNextBox = true;
|
||||
|
||||
// Clip the current span against the current box
|
||||
if (spanlox > rgnlox) {
|
||||
resultlox = spanlox;
|
||||
}
|
||||
else {
|
||||
resultlox = rgnlox;
|
||||
}
|
||||
|
||||
if (spanloy > rgnloy) {
|
||||
resultloy = spanloy;
|
||||
}
|
||||
else {
|
||||
resultloy = rgnloy;
|
||||
}
|
||||
|
||||
if (spanhix < rgnhix) {
|
||||
resulthix = spanhix;
|
||||
}
|
||||
else {
|
||||
resulthix = rgnhix;
|
||||
}
|
||||
|
||||
if (spanhiy < rgnhiy) {
|
||||
resulthiy = spanhiy;
|
||||
}
|
||||
else {
|
||||
resulthiy = rgnhiy;
|
||||
}
|
||||
|
||||
// If the result is empty, try then next box
|
||||
// otherwise return the box.
|
||||
// REMIND: I think by definition it's non-empty
|
||||
// if we're here. Need to think about this some more.
|
||||
if (resultlox >= resulthix ||
|
||||
resultloy >= resulthiy) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
resultbox[0] = resultlox;
|
||||
resultbox[1] = resultloy;
|
||||
resultbox[2] = resulthix;
|
||||
resultbox[3] = resulthiy;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method tells the iterator that it may skip all spans
|
||||
* whose Y range is completely above the indicated Y coordinate.
|
||||
*/
|
||||
public void skipDownTo(int y) {
|
||||
spanIter.skipDownTo(y);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a native pointer to a function block that
|
||||
* can be used by a native method to perform the same iteration
|
||||
* cycle that the above methods provide while avoiding upcalls to
|
||||
* the Java object.
|
||||
* The definition of the structure whose pointer is returned by
|
||||
* this method is defined in:
|
||||
* <pre>
|
||||
* src/share/native/sun/java2d/pipe/SpanIterator.h
|
||||
* </pre>
|
||||
*/
|
||||
public long getNativeIterator() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleans out all internal data structures.
|
||||
*/
|
||||
//public native void dispose();
|
||||
|
||||
protected void finalize() {
|
||||
//dispose();
|
||||
}
|
||||
|
||||
}
|
||||
101
jdkSrc/jdk8/sun/java2d/pipe/RegionIterator.java
Normal file
101
jdkSrc/jdk8/sun/java2d/pipe/RegionIterator.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2012, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Rectangle;
|
||||
|
||||
/**
|
||||
* This class defines the API for iterating through the bands
|
||||
* of a region object.
|
||||
*/
|
||||
public class RegionIterator {
|
||||
Region region;
|
||||
int curIndex;
|
||||
int numXbands;
|
||||
|
||||
RegionIterator(Region r) {
|
||||
region = r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new RegionIterator object representing the same
|
||||
* iteration state as this object to allow multiple iteration
|
||||
* branches from the current position.
|
||||
*/
|
||||
public RegionIterator createCopy() {
|
||||
RegionIterator r = new RegionIterator(region);
|
||||
r.curIndex = this.curIndex;
|
||||
r.numXbands = this.numXbands;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the iteration state from this RegionIterator object
|
||||
* into another RegionIterator object to allow multiple iteration
|
||||
* branches from the current position.
|
||||
*/
|
||||
public void copyStateFrom(RegionIterator ri) {
|
||||
if (this.region != ri.region) {
|
||||
throw new InternalError("region mismatch");
|
||||
}
|
||||
this.curIndex = ri.curIndex;
|
||||
this.numXbands = ri.numXbands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iteration state to the beginning of the next
|
||||
* Y range in the region returning true if one is found
|
||||
* and recording the low and high Y coordinates of the
|
||||
* range in the array at locations 1 and 3 respectively.
|
||||
*/
|
||||
public boolean nextYRange(int range[]) {
|
||||
curIndex += numXbands * 2;
|
||||
numXbands = 0;
|
||||
if (curIndex >= region.endIndex) {
|
||||
return false;
|
||||
}
|
||||
range[1] = region.bands[curIndex++];
|
||||
range[3] = region.bands[curIndex++];
|
||||
numXbands = region.bands[curIndex++];
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the iteration state to the beginning of the next
|
||||
* X band in the current Y range returning true if one is
|
||||
* found and recording the low and high X coordinates of
|
||||
* the range in the array at locations 0 and 2 respectively.
|
||||
*/
|
||||
public boolean nextXBand(int range[]) {
|
||||
if (numXbands <= 0) {
|
||||
return false;
|
||||
}
|
||||
numXbands--;
|
||||
range[0] = region.bands[curIndex++];
|
||||
range[2] = region.bands[curIndex++];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
210
jdkSrc/jdk8/sun/java2d/pipe/RegionSpanIterator.java
Normal file
210
jdkSrc/jdk8/sun/java2d/pipe/RegionSpanIterator.java
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2002, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* This class implements the ShapeIterator interface for a Region.
|
||||
* This is useful as the source iterator of a device clip region
|
||||
* (in its native guise), and also as the result of clipping a
|
||||
* Region to a rectangle.
|
||||
*/
|
||||
public class RegionSpanIterator implements SpanIterator {
|
||||
// The RegionIterator that we use to do the work
|
||||
RegionIterator ri;
|
||||
|
||||
// Clipping bounds
|
||||
int lox, loy, hix, hiy;
|
||||
|
||||
// Current Y band limits
|
||||
int curloy, curhiy;
|
||||
|
||||
// Are we done?
|
||||
boolean done = false;
|
||||
|
||||
// Is the associated Region rectangular?
|
||||
boolean isrect;
|
||||
|
||||
/*
|
||||
REMIND: For native implementation
|
||||
long pData; // Private storage of rect info
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
}
|
||||
|
||||
public static native void initIDs();
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructs an instance based on the given Region
|
||||
*/
|
||||
public RegionSpanIterator(Region r) {
|
||||
int[] bounds = new int[4];
|
||||
|
||||
r.getBounds(bounds);
|
||||
lox = bounds[0];
|
||||
loy = bounds[1];
|
||||
hix = bounds[2];
|
||||
hiy = bounds[3];
|
||||
isrect = r.isRectangular();
|
||||
|
||||
ri = r.getIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bbox of the available region spans.
|
||||
*/
|
||||
public void getPathBox(int pathbox[]) {
|
||||
pathbox[0] = lox;
|
||||
pathbox[1] = loy;
|
||||
pathbox[2] = hix;
|
||||
pathbox[3] = hiy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect the box used for clipping the output spans with the
|
||||
* given box.
|
||||
*/
|
||||
public void intersectClipBox(int clox, int cloy, int chix, int chiy) {
|
||||
if (clox > lox) {
|
||||
lox = clox;
|
||||
}
|
||||
if (cloy > loy) {
|
||||
loy = cloy;
|
||||
}
|
||||
if (chix < hix) {
|
||||
hix = chix;
|
||||
}
|
||||
if (chiy < hiy) {
|
||||
hiy = chiy;
|
||||
}
|
||||
done = lox >= hix || loy >= hiy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the next span that needs to be operated on.
|
||||
* If the return value is false then there are no more spans.
|
||||
*/
|
||||
public boolean nextSpan(int spanbox[]) {
|
||||
|
||||
// Quick test for end conditions
|
||||
if (done) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the Region is rectangular, we store our bounds (possibly
|
||||
// clipped via intersectClipBox()) in spanbox and return true
|
||||
// so that the caller will process the single span. We set done
|
||||
// to true to ensure that this will be the last span processed.
|
||||
if (isrect) {
|
||||
getPathBox(spanbox);
|
||||
done = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Local cache of current span's bounds
|
||||
int curlox, curhix;
|
||||
int curloy = this.curloy;
|
||||
int curhiy = this.curhiy;
|
||||
|
||||
while (true) {
|
||||
if (!ri.nextXBand(spanbox)) {
|
||||
if (!ri.nextYRange(spanbox)) {
|
||||
done = true;
|
||||
return false;
|
||||
}
|
||||
// Update the current y band and clip it
|
||||
curloy = spanbox[1];
|
||||
curhiy = spanbox[3];
|
||||
if (curloy < loy) {
|
||||
curloy = loy;
|
||||
}
|
||||
if (curhiy > hiy) {
|
||||
curhiy = hiy;
|
||||
}
|
||||
// Check for moving below the clip rect
|
||||
if (curloy >= hiy) {
|
||||
done = true;
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Clip the x box
|
||||
curlox = spanbox[0];
|
||||
curhix = spanbox[2];
|
||||
if (curlox < lox) {
|
||||
curlox = lox;
|
||||
}
|
||||
if (curhix > hix) {
|
||||
curhix = hix;
|
||||
}
|
||||
// If it's non- box, we're done
|
||||
if (curlox < curhix && curloy < curhiy) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the result and the store y range
|
||||
spanbox[0] = curlox;
|
||||
spanbox[1] = this.curloy = curloy;
|
||||
spanbox[2] = curhix;
|
||||
spanbox[3] = this.curhiy = curhiy;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tells the iterator that it may skip all spans
|
||||
* whose Y range is completely above the indicated Y coordinate.
|
||||
*/
|
||||
public void skipDownTo(int y) {
|
||||
loy = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a native pointer to a function block that
|
||||
* can be used by a native method to perform the same iteration
|
||||
* cycle that the above methods provide while avoiding upcalls to
|
||||
* the Java object.
|
||||
* The definition of the structure whose pointer is returned by
|
||||
* this method is defined in:
|
||||
* <pre>
|
||||
* src/share/native/sun/java2d/pipe/SpanIterator.h
|
||||
* </pre>
|
||||
*/
|
||||
public long getNativeIterator() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleans out all internal data structures.
|
||||
* REMIND: Native implementation
|
||||
public native void dispose();
|
||||
|
||||
protected void finalize() {
|
||||
dispose();
|
||||
}
|
||||
*/
|
||||
}
|
||||
295
jdkSrc/jdk8/sun/java2d/pipe/RenderBuffer.java
Normal file
295
jdkSrc/jdk8/sun/java2d/pipe/RenderBuffer.java
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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 sun.misc.Unsafe;
|
||||
|
||||
|
||||
/**
|
||||
* The RenderBuffer class is a simplified, high-performance, Unsafe wrapper
|
||||
* used for buffering rendering operations in a single-threaded rendering
|
||||
* environment. It's functionality is similar to the ByteBuffer and related
|
||||
* NIO classes. However, the methods in this class perform little to no
|
||||
* alignment or bounds checks for performance reasons. Therefore, it is
|
||||
* the caller's responsibility to ensure that all put() calls are properly
|
||||
* aligned and within bounds:
|
||||
* - int and float values must be aligned on 4-byte boundaries
|
||||
* - long and double values must be aligned on 8-byte boundaries
|
||||
*
|
||||
* This class only includes the bare minimum of methods to support
|
||||
* single-threaded rendering. For example, there is no put(double[]) method
|
||||
* because we currently have no need for such a method in the STR classes.
|
||||
*/
|
||||
public class RenderBuffer {
|
||||
|
||||
/**
|
||||
* These constants represent the size of various data types (in bytes).
|
||||
*/
|
||||
protected static final long SIZEOF_BYTE = 1L;
|
||||
protected static final long SIZEOF_SHORT = 2L;
|
||||
protected static final long SIZEOF_INT = 4L;
|
||||
protected static final long SIZEOF_FLOAT = 4L;
|
||||
protected static final long SIZEOF_LONG = 8L;
|
||||
protected static final long SIZEOF_DOUBLE = 8L;
|
||||
|
||||
/**
|
||||
* Represents the number of elements at which we have empirically
|
||||
* determined that the average cost of a JNI call exceeds the expense
|
||||
* of an element by element copy. In other words, if the number of
|
||||
* elements in an array to be copied exceeds this value, then we should
|
||||
* use the copyFromArray() method to complete the bulk put operation.
|
||||
* (This value can be adjusted if the cost of JNI downcalls is reduced
|
||||
* in a future release.)
|
||||
*/
|
||||
private static final int COPY_FROM_ARRAY_THRESHOLD = 6;
|
||||
|
||||
protected final Unsafe unsafe;
|
||||
protected final long baseAddress;
|
||||
protected final long endAddress;
|
||||
protected long curAddress;
|
||||
protected final int capacity;
|
||||
|
||||
protected RenderBuffer(int numBytes) {
|
||||
unsafe = Unsafe.getUnsafe();
|
||||
curAddress = baseAddress = unsafe.allocateMemory(numBytes);
|
||||
endAddress = baseAddress + numBytes;
|
||||
capacity = numBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a fresh buffer using the machine endianness.
|
||||
*/
|
||||
public static RenderBuffer allocate(int numBytes) {
|
||||
return new RenderBuffer(numBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base address of the underlying memory buffer.
|
||||
*/
|
||||
public final long getAddress() {
|
||||
return baseAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* The behavior (and names) of the following methods are nearly
|
||||
* identical to their counterparts in the various NIO Buffer classes.
|
||||
*/
|
||||
|
||||
public final int capacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public final int remaining() {
|
||||
return (int)(endAddress - curAddress);
|
||||
}
|
||||
|
||||
public final int position() {
|
||||
return (int)(curAddress - baseAddress);
|
||||
}
|
||||
|
||||
public final void position(long numBytes) {
|
||||
curAddress = baseAddress + numBytes;
|
||||
}
|
||||
|
||||
public final void clear() {
|
||||
curAddress = baseAddress;
|
||||
}
|
||||
|
||||
public final RenderBuffer skip(long numBytes) {
|
||||
curAddress += numBytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* putByte() methods...
|
||||
*/
|
||||
|
||||
public final RenderBuffer putByte(byte x) {
|
||||
unsafe.putByte(curAddress, x);
|
||||
curAddress += SIZEOF_BYTE;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RenderBuffer put(byte[] x) {
|
||||
return put(x, 0, x.length);
|
||||
}
|
||||
|
||||
public RenderBuffer put(byte[] x, int offset, int length) {
|
||||
if (length > COPY_FROM_ARRAY_THRESHOLD) {
|
||||
long offsetInBytes = offset * SIZEOF_BYTE + Unsafe.ARRAY_BYTE_BASE_OFFSET;
|
||||
long lengthInBytes = length * SIZEOF_BYTE;
|
||||
unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
|
||||
position(position() + lengthInBytes);
|
||||
} else {
|
||||
int end = offset + length;
|
||||
for (int i = offset; i < end; i++) {
|
||||
putByte(x[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* putShort() methods...
|
||||
*/
|
||||
|
||||
public final RenderBuffer putShort(short x) {
|
||||
// assert (position() % SIZEOF_SHORT == 0);
|
||||
unsafe.putShort(curAddress, x);
|
||||
curAddress += SIZEOF_SHORT;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RenderBuffer put(short[] x) {
|
||||
return put(x, 0, x.length);
|
||||
}
|
||||
|
||||
public RenderBuffer put(short[] x, int offset, int length) {
|
||||
// assert (position() % SIZEOF_SHORT == 0);
|
||||
if (length > COPY_FROM_ARRAY_THRESHOLD) {
|
||||
long offsetInBytes = offset * SIZEOF_SHORT + Unsafe.ARRAY_SHORT_BASE_OFFSET;
|
||||
long lengthInBytes = length * SIZEOF_SHORT;
|
||||
unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
|
||||
position(position() + lengthInBytes);
|
||||
} else {
|
||||
int end = offset + length;
|
||||
for (int i = offset; i < end; i++) {
|
||||
putShort(x[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* putInt() methods...
|
||||
*/
|
||||
|
||||
public final RenderBuffer putInt(int pos, int x) {
|
||||
// assert (baseAddress + pos % SIZEOF_INT == 0);
|
||||
unsafe.putInt(baseAddress + pos, x);
|
||||
return this;
|
||||
}
|
||||
|
||||
public final RenderBuffer putInt(int x) {
|
||||
// assert (position() % SIZEOF_INT == 0);
|
||||
unsafe.putInt(curAddress, x);
|
||||
curAddress += SIZEOF_INT;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RenderBuffer put(int[] x) {
|
||||
return put(x, 0, x.length);
|
||||
}
|
||||
|
||||
public RenderBuffer put(int[] x, int offset, int length) {
|
||||
// assert (position() % SIZEOF_INT == 0);
|
||||
if (length > COPY_FROM_ARRAY_THRESHOLD) {
|
||||
long offsetInBytes = offset * SIZEOF_INT + Unsafe.ARRAY_INT_BASE_OFFSET;
|
||||
long lengthInBytes = length * SIZEOF_INT;
|
||||
unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
|
||||
position(position() + lengthInBytes);
|
||||
} else {
|
||||
int end = offset + length;
|
||||
for (int i = offset; i < end; i++) {
|
||||
putInt(x[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* putFloat() methods...
|
||||
*/
|
||||
|
||||
public final RenderBuffer putFloat(float x) {
|
||||
// assert (position() % SIZEOF_FLOAT == 0);
|
||||
unsafe.putFloat(curAddress, x);
|
||||
curAddress += SIZEOF_FLOAT;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RenderBuffer put(float[] x) {
|
||||
return put(x, 0, x.length);
|
||||
}
|
||||
|
||||
public RenderBuffer put(float[] x, int offset, int length) {
|
||||
// assert (position() % SIZEOF_FLOAT == 0);
|
||||
if (length > COPY_FROM_ARRAY_THRESHOLD) {
|
||||
long offsetInBytes = offset * SIZEOF_FLOAT + Unsafe.ARRAY_FLOAT_BASE_OFFSET;
|
||||
long lengthInBytes = length * SIZEOF_FLOAT;
|
||||
unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
|
||||
position(position() + lengthInBytes);
|
||||
} else {
|
||||
int end = offset + length;
|
||||
for (int i = offset; i < end; i++) {
|
||||
putFloat(x[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* putLong() methods...
|
||||
*/
|
||||
|
||||
public final RenderBuffer putLong(long x) {
|
||||
// assert (position() % SIZEOF_LONG == 0);
|
||||
unsafe.putLong(curAddress, x);
|
||||
curAddress += SIZEOF_LONG;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RenderBuffer put(long[] x) {
|
||||
return put(x, 0, x.length);
|
||||
}
|
||||
|
||||
public RenderBuffer put(long[] x, int offset, int length) {
|
||||
// assert (position() % SIZEOF_LONG == 0);
|
||||
if (length > COPY_FROM_ARRAY_THRESHOLD) {
|
||||
long offsetInBytes = offset * SIZEOF_LONG + Unsafe.ARRAY_LONG_BASE_OFFSET;
|
||||
long lengthInBytes = length * SIZEOF_LONG;
|
||||
unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);
|
||||
position(position() + lengthInBytes);
|
||||
} else {
|
||||
int end = offset + length;
|
||||
for (int i = offset; i < end; i++) {
|
||||
putLong(x[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* putDouble() method(s)...
|
||||
*/
|
||||
|
||||
public final RenderBuffer putDouble(double x) {
|
||||
// assert (position() % SIZEOF_DOUBLE == 0);
|
||||
unsafe.putDouble(curAddress, x);
|
||||
curAddress += SIZEOF_DOUBLE;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
223
jdkSrc/jdk8/sun/java2d/pipe/RenderQueue.java
Normal file
223
jdkSrc/jdk8/sun/java2d/pipe/RenderQueue.java
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.util.HashSet;
|
||||
import java.util.Set;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
/**
|
||||
* The RenderQueue class encapsulates a RenderBuffer on which rendering
|
||||
* operations are enqueued. Note that the RenderQueue lock must be acquired
|
||||
* before performing any operations on the queue (e.g. enqueuing an operation
|
||||
* or flushing the queue). A sample usage scenario follows:
|
||||
*
|
||||
* public void drawSomething(...) {
|
||||
* rq.lock();
|
||||
* try {
|
||||
* ctx.validate(...);
|
||||
* rq.ensureCapacity(4);
|
||||
* rq.getBuffer().putInt(DRAW_SOMETHING);
|
||||
* ...
|
||||
* } finally {
|
||||
* rq.unlock();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* If you are enqueuing an operation that involves 8-byte parameters (i.e.
|
||||
* long or double values), it is imperative that you ensure proper
|
||||
* alignment of the underlying RenderBuffer. This can be accomplished
|
||||
* simply by providing an offset to the first 8-byte parameter in your
|
||||
* operation to the ensureCapacityAndAlignment() method. For example:
|
||||
*
|
||||
* public void drawStuff(...) {
|
||||
* rq.lock();
|
||||
* try {
|
||||
* RenderBuffer buf = rq.getBuffer();
|
||||
* ctx.validate(...);
|
||||
* // 28 total bytes in the operation, 12 bytes to the first long
|
||||
* rq.ensureCapacityAndAlignment(28, 12);
|
||||
* buf.putInt(DRAW_STUFF);
|
||||
* buf.putInt(x).putInt(y);
|
||||
* buf.putLong(addr1);
|
||||
* buf.putLong(addr2);
|
||||
* } finally {
|
||||
* rq.unlock();
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public abstract class RenderQueue {
|
||||
|
||||
/** The size of the underlying buffer, in bytes. */
|
||||
private static final int BUFFER_SIZE = 32000;
|
||||
|
||||
/** The underlying buffer for this queue. */
|
||||
protected RenderBuffer buf;
|
||||
|
||||
/**
|
||||
* A Set containing hard references to Objects that must stay alive until
|
||||
* the queue has been completely flushed.
|
||||
*/
|
||||
protected Set refSet;
|
||||
|
||||
protected RenderQueue() {
|
||||
refSet = new HashSet();
|
||||
buf = RenderBuffer.allocate(BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the queue for read/write access.
|
||||
*/
|
||||
public final void lock() {
|
||||
/*
|
||||
* Implementation note: In theory we should have two separate locks:
|
||||
* one lock to synchronize access to the RenderQueue, and then a
|
||||
* separate lock (the AWT lock) that only needs to be acquired when
|
||||
* we are about to flush the queue (using native windowing system
|
||||
* operations). In practice it has been difficult to enforce the
|
||||
* correct lock ordering; sometimes AWT will have already acquired
|
||||
* the AWT lock before grabbing the RQ lock (see 6253009), while the
|
||||
* expected order should be RQ lock and then AWT lock. Due to this
|
||||
* issue, using two separate locks is prone to deadlocks. Therefore,
|
||||
* to solve this issue we have decided to eliminate the separate RQ
|
||||
* lock and instead just acquire the AWT lock here. (Someday it might
|
||||
* be nice to go back to the old two-lock system, but that would
|
||||
* require potentially risky changes to AWT to ensure that it never
|
||||
* acquires the AWT lock before calling into 2D code that wants to
|
||||
* acquire the RQ lock.)
|
||||
*/
|
||||
SunToolkit.awtLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to lock the queue. If successful, this method returns true,
|
||||
* indicating that the caller is responsible for calling
|
||||
* <code>unlock</code>; otherwise this method returns false.
|
||||
*/
|
||||
public final boolean tryLock() {
|
||||
return SunToolkit.awtTryLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the queue.
|
||||
*/
|
||||
public final void unlock() {
|
||||
SunToolkit.awtUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given Object to the set of hard references, which will
|
||||
* prevent that Object from being disposed until the queue has been
|
||||
* flushed completely. This is useful in cases where some enqueued
|
||||
* data could become invalid if the reference Object were garbage
|
||||
* collected before the queue could be processed. (For example, keeping
|
||||
* a hard reference to a FontStrike will prevent any enqueued glyph
|
||||
* images associated with that strike from becoming invalid before the
|
||||
* queue is flushed.) The reference set will be cleared immediately
|
||||
* after the queue is flushed each time.
|
||||
*/
|
||||
public final void addReference(Object ref) {
|
||||
refSet.add(ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encapsulated RenderBuffer object.
|
||||
*/
|
||||
public final RenderBuffer getBuffer() {
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that there will be enough room on the underlying buffer
|
||||
* for the following operation. If the operation will not fit given
|
||||
* the remaining space, the buffer will be flushed immediately, leaving
|
||||
* an empty buffer for the impending operation.
|
||||
*
|
||||
* @param opsize size (in bytes) of the following operation
|
||||
*/
|
||||
public final void ensureCapacity(int opsize) {
|
||||
if (buf.remaining() < opsize) {
|
||||
flushNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that is equivalent to calling ensureCapacity()
|
||||
* followed by ensureAlignment(). The ensureCapacity() call allows for an
|
||||
* extra 4 bytes of space in case the ensureAlignment() method needs to
|
||||
* insert a NOOP token on the buffer.
|
||||
*
|
||||
* @param opsize size (in bytes) of the following operation
|
||||
* @param first8ByteValueOffset offset (in bytes) from the current
|
||||
* position to the first 8-byte value used in the following operation
|
||||
*/
|
||||
public final void ensureCapacityAndAlignment(int opsize,
|
||||
int first8ByteValueOffset)
|
||||
{
|
||||
ensureCapacity(opsize + 4);
|
||||
ensureAlignment(first8ByteValueOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a 4-byte NOOP token when necessary to ensure that all 8-byte
|
||||
* parameters for the following operation are added to the underlying
|
||||
* buffer with an 8-byte memory alignment.
|
||||
*
|
||||
* @param first8ByteValueOffset offset (in bytes) from the current
|
||||
* position to the first 8-byte value used in the following operation
|
||||
*/
|
||||
public final void ensureAlignment(int first8ByteValueOffset) {
|
||||
int first8ByteValuePosition = buf.position() + first8ByteValueOffset;
|
||||
if ((first8ByteValuePosition & 7) != 0) {
|
||||
buf.putInt(BufferedOpCodes.NOOP);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately processes each operation currently pending on the buffer.
|
||||
* This method will block until the entire buffer has been flushed. The
|
||||
* queue lock must be acquired before calling this method.
|
||||
*/
|
||||
public abstract void flushNow();
|
||||
|
||||
/**
|
||||
* Immediately processes each operation currently pending on the buffer,
|
||||
* and then invokes the provided task. This method will block until the
|
||||
* entire buffer has been flushed and the provided task has been executed.
|
||||
* The queue lock must be acquired before calling this method.
|
||||
*/
|
||||
public abstract void flushAndInvokeNow(Runnable task);
|
||||
|
||||
/**
|
||||
* Updates the current position of the underlying buffer, and then
|
||||
* flushes the queue immediately. This method is useful when native code
|
||||
* has added data to the queue and needs to flush immediately.
|
||||
*/
|
||||
public void flushNow(int position) {
|
||||
buf.position(position);
|
||||
flushNow();
|
||||
}
|
||||
}
|
||||
478
jdkSrc/jdk8/sun/java2d/pipe/RenderingEngine.java
Normal file
478
jdkSrc/jdk8/sun/java2d/pipe/RenderingEngine.java
Normal file
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Shape;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.AccessController;
|
||||
import java.util.ServiceLoader;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
import sun.awt.geom.PathConsumer2D;
|
||||
|
||||
/**
|
||||
* This class abstracts a number of features for which the Java 2D
|
||||
* implementation relies on proprietary licensed software libraries.
|
||||
* Access to those features is now achieved by retrieving the singleton
|
||||
* instance of this class and calling the appropriate methods on it.
|
||||
* The 3 primary features abstracted here include:
|
||||
* <dl>
|
||||
* <dt>Shape createStrokedShape(Shape, [BasicStroke attributes]);
|
||||
* <dd>This method implements the functionality of the method of the
|
||||
* same name on the {@link BasicStroke} class.
|
||||
* <dt>void strokeTo(Shape, [rendering parameters], PathConsumer2D);
|
||||
* <dd>This method performs widening of the source path on the fly
|
||||
* and sends the results to the given {@link PathConsumer2D} object.
|
||||
* This procedure avoids having to create an intermediate Shape
|
||||
* object to hold the results of the {@code createStrokedShape} method.
|
||||
* The main user of this method is the Java 2D non-antialiasing renderer.
|
||||
* <dt>AATileGenerator getAATileGenerator(Shape, [rendering parameters]);
|
||||
* <dd>This method returns an object which can iterate over the
|
||||
* specified bounding box and produce tiles of coverage values for
|
||||
* antialiased rendering. The details of the operation of the
|
||||
* {@link AATileGenerator} object are explained in its class comments.
|
||||
* </dl>
|
||||
* Additionally, the following informational method supplies important
|
||||
* data about the implementation.
|
||||
* <dl>
|
||||
* <dt>float getMinimumAAPenSize()
|
||||
* <dd>This method provides information on how small the BasicStroke
|
||||
* line width can get before dropouts occur. Rendering with a BasicStroke
|
||||
* is defined to never allow the line to have breaks, gaps, or dropouts
|
||||
* even if the width is set to 0.0f, so this information allows the
|
||||
* {@link SunGraphics2D} class to detect the "thin line" case and set
|
||||
* the rendering attributes accordingly.
|
||||
* </dl>
|
||||
* At startup the runtime will load a single instance of this class.
|
||||
* It searches the classpath for a registered provider of this API
|
||||
* and returns either the last one it finds, or the instance whose
|
||||
* class name matches the value supplied in the System property
|
||||
* {@code sun.java2d.renderer}.
|
||||
* Additionally, a runtime System property flag can be set to trace
|
||||
* all calls to methods on the {@code RenderingEngine} in use by
|
||||
* setting the sun.java2d.renderer.trace property to any non-null value.
|
||||
* <p>
|
||||
* Parts of the system that need to use any of the above features should
|
||||
* call {@code RenderingEngine.getInstance()} to obtain the properly
|
||||
* registered (and possibly trace-enabled) version of the RenderingEngine.
|
||||
*/
|
||||
public abstract class RenderingEngine {
|
||||
private static RenderingEngine reImpl;
|
||||
|
||||
/**
|
||||
* Returns an instance of {@code RenderingEngine} as determined
|
||||
* by the installation environment and runtime flags.
|
||||
* <p>
|
||||
* A specific instance of the {@code RenderingEngine} can be
|
||||
* chosen by specifying the runtime flag:
|
||||
* <pre>
|
||||
* java -Dsun.java2d.renderer=<classname>
|
||||
* </pre>
|
||||
*
|
||||
* If no specific {@code RenderingEngine} is specified on the command
|
||||
* or Ductus renderer is specified, it will attempt loading the
|
||||
* sun.dc.DuctusRenderingEngine class using Class.forName as a fastpath;
|
||||
* if not found, use the ServiceLoader.
|
||||
* If no specific {@code RenderingEngine} is specified on the command
|
||||
* line then the last one returned by enumerating all subclasses of
|
||||
* {@code RenderingEngine} known to the ServiceLoader is used.
|
||||
* <p>
|
||||
* Runtime tracing of the actions of the {@code RenderingEngine}
|
||||
* can be enabled by specifying the runtime flag:
|
||||
* <pre>
|
||||
* java -Dsun.java2d.renderer.trace=<any string>
|
||||
* </pre>
|
||||
* @return an instance of {@code RenderingEngine}
|
||||
* @since 1.7
|
||||
*/
|
||||
public static synchronized RenderingEngine getInstance() {
|
||||
if (reImpl != null) {
|
||||
return reImpl;
|
||||
}
|
||||
|
||||
reImpl =
|
||||
AccessController.doPrivileged(new PrivilegedAction<RenderingEngine>() {
|
||||
public RenderingEngine run() {
|
||||
final String ductusREClass = "sun.dc.DuctusRenderingEngine";
|
||||
String reClass =
|
||||
System.getProperty("sun.java2d.renderer", ductusREClass);
|
||||
if (reClass.equals(ductusREClass)) {
|
||||
try {
|
||||
Class<?> cls = Class.forName(ductusREClass);
|
||||
return (RenderingEngine) cls.newInstance();
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
// not found
|
||||
}
|
||||
}
|
||||
|
||||
ServiceLoader<RenderingEngine> reLoader =
|
||||
ServiceLoader.loadInstalled(RenderingEngine.class);
|
||||
|
||||
RenderingEngine service = null;
|
||||
|
||||
for (RenderingEngine re : reLoader) {
|
||||
service = re;
|
||||
if (re.getClass().getName().equals(reClass)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return service;
|
||||
}
|
||||
});
|
||||
|
||||
if (reImpl == null) {
|
||||
throw new InternalError("No RenderingEngine module found");
|
||||
}
|
||||
|
||||
GetPropertyAction gpa =
|
||||
new GetPropertyAction("sun.java2d.renderer.trace");
|
||||
String reTrace = AccessController.doPrivileged(gpa);
|
||||
if (reTrace != null) {
|
||||
reImpl = new Tracer(reImpl);
|
||||
}
|
||||
|
||||
return reImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a widened path as specified by the parameters.
|
||||
* <p>
|
||||
* The specified {@code src} {@link Shape} is widened according
|
||||
* to the specified attribute parameters as per the
|
||||
* {@link BasicStroke} specification.
|
||||
*
|
||||
* @param src the source path to be widened
|
||||
* @param width the width of the widened path as per {@code BasicStroke}
|
||||
* @param caps the end cap decorations as per {@code BasicStroke}
|
||||
* @param join the segment join decorations as per {@code BasicStroke}
|
||||
* @param miterlimit the miter limit as per {@code BasicStroke}
|
||||
* @param dashes the dash length array as per {@code BasicStroke}
|
||||
* @param dashphase the initial dash phase as per {@code BasicStroke}
|
||||
* @return the widened path stored in a new {@code Shape} object
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract Shape createStrokedShape(Shape src,
|
||||
float width,
|
||||
int caps,
|
||||
int join,
|
||||
float miterlimit,
|
||||
float dashes[],
|
||||
float dashphase);
|
||||
|
||||
/**
|
||||
* Sends the geometry for a widened path as specified by the parameters
|
||||
* to the specified consumer.
|
||||
* <p>
|
||||
* The specified {@code src} {@link Shape} is widened according
|
||||
* to the parameters specified by the {@link BasicStroke} object.
|
||||
* Adjustments are made to the path as appropriate for the
|
||||
* {@link VALUE_STROKE_NORMALIZE} hint if the {@code normalize}
|
||||
* boolean parameter is true.
|
||||
* Adjustments are made to the path as appropriate for the
|
||||
* {@link VALUE_ANTIALIAS_ON} hint if the {@code antialias}
|
||||
* boolean parameter is true.
|
||||
* <p>
|
||||
* The geometry of the widened path is forwarded to the indicated
|
||||
* {@link PathConsumer2D} object as it is calculated.
|
||||
*
|
||||
* @param src the source path to be widened
|
||||
* @param bs the {@code BasicSroke} object specifying the
|
||||
* decorations to be applied to the widened path
|
||||
* @param normalize indicates whether stroke normalization should
|
||||
* be applied
|
||||
* @param antialias indicates whether or not adjustments appropriate
|
||||
* to antialiased rendering should be applied
|
||||
* @param consumer the {@code PathConsumer2D} instance to forward
|
||||
* the widened geometry to
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract void strokeTo(Shape src,
|
||||
AffineTransform at,
|
||||
BasicStroke bs,
|
||||
boolean thin,
|
||||
boolean normalize,
|
||||
boolean antialias,
|
||||
PathConsumer2D consumer);
|
||||
|
||||
/**
|
||||
* Construct an antialiased tile generator for the given shape with
|
||||
* the given rendering attributes and store the bounds of the tile
|
||||
* iteration in the bbox parameter.
|
||||
* The {@code at} parameter specifies a transform that should affect
|
||||
* both the shape and the {@code BasicStroke} attributes.
|
||||
* The {@code clip} parameter specifies the current clip in effect
|
||||
* in device coordinates and can be used to prune the data for the
|
||||
* operation, but the renderer is not required to perform any
|
||||
* clipping.
|
||||
* If the {@code BasicStroke} parameter is null then the shape
|
||||
* should be filled as is, otherwise the attributes of the
|
||||
* {@code BasicStroke} should be used to specify a draw operation.
|
||||
* The {@code thin} parameter indicates whether or not the
|
||||
* transformed {@code BasicStroke} represents coordinates smaller
|
||||
* than the minimum resolution of the antialiasing rasterizer as
|
||||
* specified by the {@code getMinimumAAPenWidth()} method.
|
||||
* <p>
|
||||
* Upon returning, this method will fill the {@code bbox} parameter
|
||||
* with 4 values indicating the bounds of the iteration of the
|
||||
* tile generator.
|
||||
* The iteration order of the tiles will be as specified by the
|
||||
* pseudo-code:
|
||||
* <pre>
|
||||
* for (y = bbox[1]; y < bbox[3]; y += tileheight) {
|
||||
* for (x = bbox[0]; x < bbox[2]; x += tilewidth) {
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* If there is no output to be rendered, this method may return
|
||||
* null.
|
||||
*
|
||||
* @param s the shape to be rendered (fill or draw)
|
||||
* @param at the transform to be applied to the shape and the
|
||||
* stroke attributes
|
||||
* @param clip the current clip in effect in device coordinates
|
||||
* @param bs if non-null, a {@code BasicStroke} whose attributes
|
||||
* should be applied to this operation
|
||||
* @param thin true if the transformed stroke attributes are smaller
|
||||
* than the minimum dropout pen width
|
||||
* @param normalize true if the {@code VALUE_STROKE_NORMALIZE}
|
||||
* {@code RenderingHint} is in effect
|
||||
* @param bbox returns the bounds of the iteration
|
||||
* @return the {@code AATileGenerator} instance to be consulted
|
||||
* for tile coverages, or null if there is no output to render
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract AATileGenerator getAATileGenerator(Shape s,
|
||||
AffineTransform at,
|
||||
Region clip,
|
||||
BasicStroke bs,
|
||||
boolean thin,
|
||||
boolean normalize,
|
||||
int bbox[]);
|
||||
|
||||
/**
|
||||
* Construct an antialiased tile generator for the given parallelogram
|
||||
* store the bounds of the tile iteration in the bbox parameter.
|
||||
* The parallelogram is specified as a starting point and 2 delta
|
||||
* vectors that indicate the slopes of the 2 pairs of sides of the
|
||||
* parallelogram.
|
||||
* The 4 corners of the parallelogram are defined by the 4 points:
|
||||
* <ul>
|
||||
* <li> {@code x}, {@code y}
|
||||
* <li> {@code x+dx1}, {@code y+dy1}
|
||||
* <li> {@code x+dx1+dx2}, {@code y+dy1+dy2}
|
||||
* <li> {@code x+dx2}, {@code y+dy2}
|
||||
* </ul>
|
||||
* The {@code lw1} and {@code lw2} parameters provide a specification
|
||||
* for an optionally stroked parallelogram if they are positive numbers.
|
||||
* The {@code lw1} parameter is the ratio of the length of the {@code dx1},
|
||||
* {@code dx2} delta vector to half of the line width in that same
|
||||
* direction.
|
||||
* The {@code lw2} parameter provides the same ratio for the other delta
|
||||
* vector.
|
||||
* If {@code lw1} and {@code lw2} are both greater than zero, then
|
||||
* the parallelogram figure is doubled by both expanding and contracting
|
||||
* each delta vector by its corresponding {@code lw} value.
|
||||
* If either (@code lw1) or {@code lw2} are also greater than 1, then
|
||||
* the inner (contracted) parallelogram disappears and the figure is
|
||||
* simply a single expanded parallelogram.
|
||||
* The {@code clip} parameter specifies the current clip in effect
|
||||
* in device coordinates and can be used to prune the data for the
|
||||
* operation, but the renderer is not required to perform any
|
||||
* clipping.
|
||||
* <p>
|
||||
* Upon returning, this method will fill the {@code bbox} parameter
|
||||
* with 4 values indicating the bounds of the iteration of the
|
||||
* tile generator.
|
||||
* The iteration order of the tiles will be as specified by the
|
||||
* pseudo-code:
|
||||
* <pre>
|
||||
* for (y = bbox[1]; y < bbox[3]; y += tileheight) {
|
||||
* for (x = bbox[0]; x < bbox[2]; x += tilewidth) {
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* If there is no output to be rendered, this method may return
|
||||
* null.
|
||||
*
|
||||
* @param x the X coordinate of the first corner of the parallelogram
|
||||
* @param y the Y coordinate of the first corner of the parallelogram
|
||||
* @param dx1 the X coordinate delta of the first leg of the parallelogram
|
||||
* @param dy1 the Y coordinate delta of the first leg of the parallelogram
|
||||
* @param dx2 the X coordinate delta of the second leg of the parallelogram
|
||||
* @param dy2 the Y coordinate delta of the second leg of the parallelogram
|
||||
* @param lw1 the line width ratio for the first leg of the parallelogram
|
||||
* @param lw2 the line width ratio for the second leg of the parallelogram
|
||||
* @param clip the current clip in effect in device coordinates
|
||||
* @param bbox returns the bounds of the iteration
|
||||
* @return the {@code AATileGenerator} instance to be consulted
|
||||
* for tile coverages, or null if there is no output to render
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract AATileGenerator getAATileGenerator(double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2,
|
||||
Region clip,
|
||||
int bbox[]);
|
||||
|
||||
/**
|
||||
* Returns the minimum pen width that the antialiasing rasterizer
|
||||
* can represent without dropouts occurring.
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract float getMinimumAAPenSize();
|
||||
|
||||
/**
|
||||
* Utility method to feed a {@link PathConsumer2D} object from a
|
||||
* given {@link PathIterator}.
|
||||
* This method deals with the details of running the iterator and
|
||||
* feeding the consumer a segment at a time.
|
||||
*/
|
||||
public static void feedConsumer(PathIterator pi, PathConsumer2D consumer) {
|
||||
float coords[] = new float[6];
|
||||
while (!pi.isDone()) {
|
||||
switch (pi.currentSegment(coords)) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
consumer.moveTo(coords[0], coords[1]);
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
consumer.lineTo(coords[0], coords[1]);
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
consumer.quadTo(coords[0], coords[1],
|
||||
coords[2], coords[3]);
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
consumer.curveTo(coords[0], coords[1],
|
||||
coords[2], coords[3],
|
||||
coords[4], coords[5]);
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
consumer.closePath();
|
||||
break;
|
||||
}
|
||||
pi.next();
|
||||
}
|
||||
}
|
||||
|
||||
static class Tracer extends RenderingEngine {
|
||||
RenderingEngine target;
|
||||
String name;
|
||||
|
||||
public Tracer(RenderingEngine target) {
|
||||
this.target = target;
|
||||
name = target.getClass().getName();
|
||||
}
|
||||
|
||||
public Shape createStrokedShape(Shape src,
|
||||
float width,
|
||||
int caps,
|
||||
int join,
|
||||
float miterlimit,
|
||||
float dashes[],
|
||||
float dashphase)
|
||||
{
|
||||
System.out.println(name+".createStrokedShape("+
|
||||
src.getClass().getName()+", "+
|
||||
"width = "+width+", "+
|
||||
"caps = "+caps+", "+
|
||||
"join = "+join+", "+
|
||||
"miter = "+miterlimit+", "+
|
||||
"dashes = "+dashes+", "+
|
||||
"dashphase = "+dashphase+")");
|
||||
return target.createStrokedShape(src,
|
||||
width, caps, join, miterlimit,
|
||||
dashes, dashphase);
|
||||
}
|
||||
|
||||
public void strokeTo(Shape src,
|
||||
AffineTransform at,
|
||||
BasicStroke bs,
|
||||
boolean thin,
|
||||
boolean normalize,
|
||||
boolean antialias,
|
||||
PathConsumer2D consumer)
|
||||
{
|
||||
System.out.println(name+".strokeTo("+
|
||||
src.getClass().getName()+", "+
|
||||
at+", "+
|
||||
bs+", "+
|
||||
(thin ? "thin" : "wide")+", "+
|
||||
(normalize ? "normalized" : "pure")+", "+
|
||||
(antialias ? "AA" : "non-AA")+", "+
|
||||
consumer.getClass().getName()+")");
|
||||
target.strokeTo(src, at, bs, thin, normalize, antialias, consumer);
|
||||
}
|
||||
|
||||
public float getMinimumAAPenSize() {
|
||||
System.out.println(name+".getMinimumAAPenSize()");
|
||||
return target.getMinimumAAPenSize();
|
||||
}
|
||||
|
||||
public AATileGenerator getAATileGenerator(Shape s,
|
||||
AffineTransform at,
|
||||
Region clip,
|
||||
BasicStroke bs,
|
||||
boolean thin,
|
||||
boolean normalize,
|
||||
int bbox[])
|
||||
{
|
||||
System.out.println(name+".getAATileGenerator("+
|
||||
s.getClass().getName()+", "+
|
||||
at+", "+
|
||||
clip+", "+
|
||||
bs+", "+
|
||||
(thin ? "thin" : "wide")+", "+
|
||||
(normalize ? "normalized" : "pure")+")");
|
||||
return target.getAATileGenerator(s, at, clip,
|
||||
bs, thin, normalize,
|
||||
bbox);
|
||||
}
|
||||
public AATileGenerator getAATileGenerator(double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2,
|
||||
Region clip,
|
||||
int bbox[])
|
||||
{
|
||||
System.out.println(name+".getAATileGenerator("+
|
||||
x+", "+y+", "+
|
||||
dx1+", "+dy1+", "+
|
||||
dx2+", "+dy2+", "+
|
||||
lw1+", "+lw2+", "+
|
||||
clip+")");
|
||||
return target.getAATileGenerator(x, y,
|
||||
dx1, dy1,
|
||||
dx2, dy2,
|
||||
lw1, lw2,
|
||||
clip, bbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
jdkSrc/jdk8/sun/java2d/pipe/ShapeDrawPipe.java
Normal file
40
jdkSrc/jdk8/sun/java2d/pipe/ShapeDrawPipe.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Shape;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This interface defines the set of calls that pipeline objects
|
||||
* can use to pass on responsibility for drawing generic Shape
|
||||
* objects.
|
||||
*/
|
||||
public interface ShapeDrawPipe {
|
||||
public void draw(SunGraphics2D sg, Shape s);
|
||||
|
||||
public void fill(SunGraphics2D sg, Shape s);
|
||||
}
|
||||
201
jdkSrc/jdk8/sun/java2d/pipe/ShapeSpanIterator.java
Normal file
201
jdkSrc/jdk8/sun/java2d/pipe/ShapeSpanIterator.java
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.geom.PathIterator;
|
||||
import java.awt.Rectangle;
|
||||
import sun.awt.geom.PathConsumer2D;
|
||||
|
||||
/**
|
||||
* This class can iterate individual span elements generated by scan
|
||||
* converting a Shape.
|
||||
* This particular implementation flattens the incoming path and then
|
||||
* performs simple polygon tracing to calculate the spans.
|
||||
*
|
||||
* Note that this class holds pointers to native data which must be
|
||||
* disposed. It is not marked as finalizable since it is intended
|
||||
* to be very lightweight and finalization is a comparitively expensive
|
||||
* procedure. The caller must specifically use try{} finally{} to
|
||||
* manually ensure that the object is disposed after use, otherwise
|
||||
* native data structures might be leaked.
|
||||
*
|
||||
* Here is a code sample for using this class:
|
||||
*
|
||||
* public void fillShape(Shape s, Rectangle clipRect) {
|
||||
* ShapeSpanIterator ssi = new ShapeSpanIterator(false);
|
||||
* try {
|
||||
* ssi.setOutputArea(clipRect);
|
||||
* ssi.appendPath(s.getPathIterator(null));
|
||||
* int spanbox[] = new int[4];
|
||||
* while (ssi.nextSpan(spanbox)) {
|
||||
* int x = spanbox[0];
|
||||
* int y = spanbox[1];
|
||||
* int w = spanbox[2] - x;
|
||||
* int h = spanbox[3] - y;
|
||||
* fillRect(x, y, w, h);
|
||||
* }
|
||||
* } finally {
|
||||
* ssi.dispose();
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public final class ShapeSpanIterator
|
||||
implements SpanIterator, PathConsumer2D
|
||||
{
|
||||
long pData;
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
}
|
||||
|
||||
public static native void initIDs();
|
||||
|
||||
public ShapeSpanIterator(boolean adjust) {
|
||||
setNormalize(adjust);
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends the geometry and winding rule from the indicated
|
||||
* path iterator.
|
||||
*/
|
||||
public void appendPath(PathIterator pi) {
|
||||
float coords[] = new float[6];
|
||||
|
||||
setRule(pi.getWindingRule());
|
||||
while (!pi.isDone()) {
|
||||
addSegment(pi.currentSegment(coords), coords);
|
||||
pi.next();
|
||||
}
|
||||
pathDone();
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends the geometry from the indicated set of polygon points.
|
||||
*/
|
||||
public native void appendPoly(int xPoints[], int yPoints[], int nPoints,
|
||||
int xoff, int yoff);
|
||||
|
||||
/*
|
||||
* Sets the normalization flag so that incoming data is
|
||||
* adjusted to nearest (0.25, 0.25) subpixel position.
|
||||
*/
|
||||
private native void setNormalize(boolean adjust);
|
||||
|
||||
/*
|
||||
* Sets the rectangle of interest for storing and returning
|
||||
* span segments.
|
||||
*/
|
||||
public void setOutputAreaXYWH(int x, int y, int w, int h) {
|
||||
setOutputAreaXYXY(x, y, Region.dimAdd(x, w), Region.dimAdd(y, h));
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the rectangle of interest for storing and returning
|
||||
* span segments.
|
||||
*/
|
||||
public native void setOutputAreaXYXY(int lox, int loy, int hix, int hiy);
|
||||
|
||||
/*
|
||||
* Sets the rectangle of interest for storing and returning
|
||||
* span segments to the specified Rectangle.
|
||||
*/
|
||||
public void setOutputArea(Rectangle r) {
|
||||
setOutputAreaXYWH(r.x, r.y, r.width, r.height);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the rectangle of interest for storing and returning
|
||||
* span segments to the bounds of the specified Region.
|
||||
*/
|
||||
public void setOutputArea(Region r) {
|
||||
setOutputAreaXYXY(r.lox, r.loy, r.hix, r.hiy);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the winding rule in the native data structures.
|
||||
*/
|
||||
public native void setRule(int rule);
|
||||
|
||||
/*
|
||||
* Adds a single PathIterator segment to the internal list of
|
||||
* path element structures.
|
||||
*/
|
||||
public native void addSegment(int type, float coords[]);
|
||||
|
||||
/*
|
||||
* Gets the bbox of the available path segments, clipped to the
|
||||
* OutputArea.
|
||||
*/
|
||||
public native void getPathBox(int pathbox[]);
|
||||
|
||||
/*
|
||||
* Intersects the path box with the given bbox.
|
||||
* Returned spans are clipped to this region, or discarded
|
||||
* altogether if they lie outside it.
|
||||
*/
|
||||
public native void intersectClipBox(int lox, int loy, int hix, int hiy);
|
||||
|
||||
/*
|
||||
* Fetches the next span that needs to be operated on.
|
||||
* If the return value is false then there are no more spans.
|
||||
*/
|
||||
public native boolean nextSpan(int spanbox[]);
|
||||
|
||||
/**
|
||||
* This method tells the iterator that it may skip all spans
|
||||
* whose Y range is completely above the indicated Y coordinate.
|
||||
*/
|
||||
public native void skipDownTo(int y);
|
||||
|
||||
/**
|
||||
* This method returns a native pointer to a function block that
|
||||
* can be used by a native method to perform the same iteration
|
||||
* cycle that the above methods provide while avoiding upcalls to
|
||||
* the Java object.
|
||||
* The definition of the structure whose pointer is returned by
|
||||
* this method is defined in:
|
||||
* <pre>
|
||||
* src/share/native/sun/java2d/pipe/SpanIterator.h
|
||||
* </pre>
|
||||
*/
|
||||
public native long getNativeIterator();
|
||||
|
||||
/*
|
||||
* Cleans out all internal data structures.
|
||||
*/
|
||||
public native void dispose();
|
||||
|
||||
public native void moveTo(float x, float y);
|
||||
public native void lineTo(float x, float y);
|
||||
public native void quadTo(float x1, float y1,
|
||||
float x2, float y2);
|
||||
public native void curveTo(float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3);
|
||||
public native void closePath();
|
||||
public native void pathDone();
|
||||
public native long getNativeConsumer();
|
||||
}
|
||||
44
jdkSrc/jdk8/sun/java2d/pipe/SolidTextRenderer.java
Normal file
44
jdkSrc/jdk8/sun/java2d/pipe/SolidTextRenderer.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2005, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.font.GlyphVector;
|
||||
import sun.awt.SunHints;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.font.GlyphList;
|
||||
|
||||
/**
|
||||
* A delegate pipe of SG2D for drawing text with
|
||||
* a solid source colour to an opaque destination.
|
||||
*/
|
||||
|
||||
public class SolidTextRenderer extends GlyphListLoopPipe
|
||||
implements LoopBasedPipe
|
||||
{
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
|
||||
sg2d.loops.drawGlyphListLoop.DrawGlyphList(sg2d, sg2d.surfaceData, gl);
|
||||
}
|
||||
}
|
||||
141
jdkSrc/jdk8/sun/java2d/pipe/SpanClipRenderer.java
Normal file
141
jdkSrc/jdk8/sun/java2d/pipe/SpanClipRenderer.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 1999, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.PathIterator;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
|
||||
/**
|
||||
* This class uses a Region iterator to modify the extents of alpha
|
||||
* tiles created during Shape rendering based upon a non-rectangular
|
||||
* clipping path.
|
||||
*/
|
||||
public class SpanClipRenderer implements CompositePipe
|
||||
{
|
||||
CompositePipe outpipe;
|
||||
|
||||
static Class RegionClass = Region.class;
|
||||
static Class RegionIteratorClass = RegionIterator.class;
|
||||
|
||||
static {
|
||||
initIDs(RegionClass, RegionIteratorClass);
|
||||
}
|
||||
|
||||
static native void initIDs(Class rc, Class ric);
|
||||
|
||||
public SpanClipRenderer(CompositePipe pipe) {
|
||||
outpipe = pipe;
|
||||
}
|
||||
|
||||
class SCRcontext {
|
||||
RegionIterator iterator;
|
||||
Object outcontext;
|
||||
int band[];
|
||||
byte tile[];
|
||||
|
||||
public SCRcontext(RegionIterator ri, Object outctx) {
|
||||
iterator = ri;
|
||||
outcontext = outctx;
|
||||
band = new int[4];
|
||||
}
|
||||
}
|
||||
|
||||
public Object startSequence(SunGraphics2D sg, Shape s, Rectangle devR,
|
||||
int[] abox) {
|
||||
RegionIterator ri = sg.clipRegion.getIterator();
|
||||
|
||||
return new SCRcontext(ri, outpipe.startSequence(sg, s, devR, abox));
|
||||
}
|
||||
|
||||
public boolean needTile(Object ctx, int x, int y, int w, int h) {
|
||||
SCRcontext context = (SCRcontext) ctx;
|
||||
return (outpipe.needTile(context.outcontext, x, y, w, h));
|
||||
}
|
||||
|
||||
public void renderPathTile(Object ctx,
|
||||
byte[] atile, int offset, int tsize,
|
||||
int x, int y, int w, int h,
|
||||
ShapeSpanIterator sr) {
|
||||
renderPathTile(ctx, atile, offset, tsize, x, y, w, h);
|
||||
}
|
||||
|
||||
public void renderPathTile(Object ctx,
|
||||
byte[] atile, int offset, int tsize,
|
||||
int x, int y, int w, int h) {
|
||||
SCRcontext context = (SCRcontext) ctx;
|
||||
RegionIterator ri = context.iterator.createCopy();
|
||||
int[] band = context.band;
|
||||
band[0] = x;
|
||||
band[1] = y;
|
||||
band[2] = x + w;
|
||||
band[3] = y + h;
|
||||
if (atile == null) {
|
||||
int size = w * h;
|
||||
atile = context.tile;
|
||||
if (atile != null && atile.length < size) {
|
||||
atile = null;
|
||||
}
|
||||
if (atile == null) {
|
||||
atile = new byte[size];
|
||||
context.tile = atile;
|
||||
}
|
||||
offset = 0;
|
||||
tsize = w;
|
||||
fillTile(ri, atile, offset, tsize, band);
|
||||
} else {
|
||||
eraseTile(ri, atile, offset, tsize, band);
|
||||
}
|
||||
|
||||
if (band[2] > band[0] && band[3] > band[1]) {
|
||||
offset += (band[1] - y) * tsize + (band[0] - x);
|
||||
outpipe.renderPathTile(context.outcontext,
|
||||
atile, offset, tsize,
|
||||
band[0], band[1],
|
||||
band[2] - band[0],
|
||||
band[3] - band[1]);
|
||||
}
|
||||
}
|
||||
|
||||
public native void fillTile(RegionIterator ri,
|
||||
byte[] alpha, int offset, int tsize,
|
||||
int[] band);
|
||||
|
||||
public native void eraseTile(RegionIterator ri,
|
||||
byte[] alpha, int offset, int tsize,
|
||||
int[] band);
|
||||
|
||||
public void skipTile(Object ctx, int x, int y) {
|
||||
SCRcontext context = (SCRcontext) ctx;
|
||||
outpipe.skipTile(context.outcontext, x, y);
|
||||
}
|
||||
|
||||
public void endSequence(Object ctx) {
|
||||
SCRcontext context = (SCRcontext) ctx;
|
||||
outpipe.endSequence(context.outcontext);
|
||||
}
|
||||
}
|
||||
95
jdkSrc/jdk8/sun/java2d/pipe/SpanIterator.java
Normal file
95
jdkSrc/jdk8/sun/java2d/pipe/SpanIterator.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 1999, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* This interface defines a general method for iterating through the
|
||||
* rectangular "spans" that represent the interior of a filled path.
|
||||
* <p>
|
||||
* There can be many kinds of span iterators used in the rendering
|
||||
* pipeline, the most basic being an iterator that scan converts a
|
||||
* path defined by any PathIterator, or an nested iterator which
|
||||
* intersects another iterator's spans with a clip region.
|
||||
* Other iterators can be created for scan converting some of the
|
||||
* primitive shapes more explicitly for speed or quality.
|
||||
*
|
||||
* @author Jim Graham
|
||||
*/
|
||||
public interface SpanIterator {
|
||||
/**
|
||||
* This method returns the bounding box of the spans that the
|
||||
* iterator will be returning.
|
||||
* The array must be of length at least 4 and upon return, it
|
||||
* will be filled with the values:
|
||||
* <pre>
|
||||
* {PathMinX, PathMinY, PathMaxX, PathMaxY}.
|
||||
* </pre>
|
||||
*/
|
||||
public void getPathBox(int pathbox[]);
|
||||
|
||||
/**
|
||||
* This method constrains the spans returned by nextSpan() to the
|
||||
* rectangle whose bounds are given.
|
||||
*/
|
||||
public void intersectClipBox(int lox, int loy, int hix, int hiy);
|
||||
|
||||
/**
|
||||
* This method returns the next span in the shape being iterated.
|
||||
* The array must be of length at least 4 and upon return, it
|
||||
* will be filled with the values:
|
||||
* <pre>
|
||||
* {SpanMinX, SpanMinY, SpanMaxX, SpanMaxY}.
|
||||
* </pre>
|
||||
*/
|
||||
public boolean nextSpan(int spanbox[]);
|
||||
|
||||
/**
|
||||
* This method tells the iterator that it may skip all spans
|
||||
* whose Y range is completely above the indicated Y coordinate.
|
||||
* This method is used to provide feedback from the caller when
|
||||
* clipping prevents the display of any data in a given Y range.
|
||||
* Typically it will only be called when this iterator has returned
|
||||
* a span whose MaxY coordinate is less than the indicated Y and
|
||||
* the calling mechanism wants to avoid unnecessary iteration work.
|
||||
* While this request could technically be ignored (i.e. a NOP),
|
||||
* doing so could potentially cause the caller to make this callback
|
||||
* for each span that is being skipped.
|
||||
*/
|
||||
public void skipDownTo(int y);
|
||||
|
||||
/**
|
||||
* This method returns a native pointer to a function block that
|
||||
* can be used by a native method to perform the same iteration
|
||||
* cycle that the above methods provide while avoiding upcalls to
|
||||
* the Java object.
|
||||
* The definition of the structure whose pointer is returned by
|
||||
* this method is defined in:
|
||||
* <pre>
|
||||
* src/share/native/sun/java2d/pipe/SpanIterator.h
|
||||
* </pre>
|
||||
*/
|
||||
public long getNativeIterator();
|
||||
}
|
||||
216
jdkSrc/jdk8/sun/java2d/pipe/SpanShapeRenderer.java
Normal file
216
jdkSrc/jdk8/sun/java2d/pipe/SpanShapeRenderer.java
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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 sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import sun.awt.SunHints;
|
||||
|
||||
/**
|
||||
* This class is used to convert raw geometry into a span iterator
|
||||
* object using a simple flattening polygon scan converter.
|
||||
* The iterator can be passed on to special SpanFiller loops to
|
||||
* perform the actual rendering.
|
||||
*/
|
||||
public abstract class SpanShapeRenderer implements ShapeDrawPipe {
|
||||
final static RenderingEngine RenderEngine = RenderingEngine.getInstance();
|
||||
|
||||
public static class Composite extends SpanShapeRenderer {
|
||||
CompositePipe comppipe;
|
||||
|
||||
public Composite(CompositePipe pipe) {
|
||||
comppipe = pipe;
|
||||
}
|
||||
|
||||
public Object startSequence(SunGraphics2D sg, Shape s,
|
||||
Rectangle devR, int[] bbox) {
|
||||
return comppipe.startSequence(sg, s, devR, bbox);
|
||||
}
|
||||
|
||||
public void renderBox(Object ctx, int x, int y, int w, int h) {
|
||||
comppipe.renderPathTile(ctx, null, 0, w, x, y, w, h);
|
||||
}
|
||||
|
||||
public void endSequence(Object ctx) {
|
||||
comppipe.endSequence(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Simple extends SpanShapeRenderer
|
||||
implements LoopBasedPipe
|
||||
{
|
||||
public Object startSequence(SunGraphics2D sg, Shape s,
|
||||
Rectangle devR, int[] bbox) {
|
||||
return sg;
|
||||
}
|
||||
|
||||
public void renderBox(Object ctx, int x, int y, int w, int h) {
|
||||
SunGraphics2D sg2d = (SunGraphics2D) ctx;
|
||||
SurfaceData sd = sg2d.getSurfaceData();
|
||||
sg2d.loops.fillRectLoop.FillRect(sg2d, sd, x, y, w, h);
|
||||
}
|
||||
|
||||
public void endSequence(Object ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(SunGraphics2D sg, Shape s) {
|
||||
if (sg.stroke instanceof BasicStroke) {
|
||||
ShapeSpanIterator sr = LoopPipe.getStrokeSpans(sg, s);
|
||||
try {
|
||||
renderSpans(sg, sg.getCompClip(), s, sr);
|
||||
} finally {
|
||||
sr.dispose();
|
||||
}
|
||||
} else {
|
||||
fill(sg, sg.stroke.createStrokedShape(s));
|
||||
}
|
||||
}
|
||||
|
||||
public static final int NON_RECTILINEAR_TRANSFORM_MASK =
|
||||
(AffineTransform.TYPE_GENERAL_TRANSFORM |
|
||||
AffineTransform.TYPE_GENERAL_ROTATION);
|
||||
|
||||
public void fill(SunGraphics2D sg, Shape s) {
|
||||
if (s instanceof Rectangle2D &&
|
||||
(sg.transform.getType() & NON_RECTILINEAR_TRANSFORM_MASK) == 0)
|
||||
{
|
||||
renderRect(sg, (Rectangle2D) s);
|
||||
return;
|
||||
}
|
||||
|
||||
Region clipRegion = sg.getCompClip();
|
||||
ShapeSpanIterator sr = LoopPipe.getFillSSI(sg);
|
||||
try {
|
||||
sr.setOutputArea(clipRegion);
|
||||
sr.appendPath(s.getPathIterator(sg.transform));
|
||||
renderSpans(sg, clipRegion, s, sr);
|
||||
} finally {
|
||||
sr.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Object startSequence(SunGraphics2D sg, Shape s,
|
||||
Rectangle devR, int[] bbox);
|
||||
|
||||
public abstract void renderBox(Object ctx, int x, int y, int w, int h);
|
||||
|
||||
public abstract void endSequence(Object ctx);
|
||||
|
||||
public void renderRect(SunGraphics2D sg, Rectangle2D r) {
|
||||
double corners[] = {
|
||||
r.getX(), r.getY(), r.getWidth(), r.getHeight(),
|
||||
};
|
||||
corners[2] += corners[0];
|
||||
corners[3] += corners[1];
|
||||
if (corners[2] <= corners[0] || corners[3] <= corners[1]) {
|
||||
return;
|
||||
}
|
||||
sg.transform.transform(corners, 0, corners, 0, 2);
|
||||
if (corners[2] < corners[0]) {
|
||||
double t = corners[2];
|
||||
corners[2] = corners[0];
|
||||
corners[0] = t;
|
||||
}
|
||||
if (corners[3] < corners[1]) {
|
||||
double t = corners[3];
|
||||
corners[3] = corners[1];
|
||||
corners[1] = t;
|
||||
}
|
||||
int abox[] = {
|
||||
(int) corners[0],
|
||||
(int) corners[1],
|
||||
(int) corners[2],
|
||||
(int) corners[3],
|
||||
};
|
||||
Rectangle devR = new Rectangle(abox[0], abox[1],
|
||||
abox[2] - abox[0],
|
||||
abox[3] - abox[1]);
|
||||
Region clipRegion = sg.getCompClip();
|
||||
clipRegion.clipBoxToBounds(abox);
|
||||
if (abox[0] >= abox[2] || abox[1] >= abox[3]) {
|
||||
return;
|
||||
}
|
||||
Object context = startSequence(sg, r, devR, abox);
|
||||
if (clipRegion.isRectangular()) {
|
||||
renderBox(context, abox[0], abox[1],
|
||||
abox[2] - abox[0],
|
||||
abox[3] - abox[1]);
|
||||
} else {
|
||||
SpanIterator sr = clipRegion.getSpanIterator(abox);
|
||||
while (sr.nextSpan(abox)) {
|
||||
renderBox(context, abox[0], abox[1],
|
||||
abox[2] - abox[0],
|
||||
abox[3] - abox[1]);
|
||||
}
|
||||
}
|
||||
endSequence(context);
|
||||
}
|
||||
|
||||
public void renderSpans(SunGraphics2D sg, Region clipRegion, Shape s,
|
||||
ShapeSpanIterator sr)
|
||||
{
|
||||
Object context = null;
|
||||
int abox[] = new int[4];
|
||||
try {
|
||||
sr.getPathBox(abox);
|
||||
Rectangle devR = new Rectangle(abox[0], abox[1],
|
||||
abox[2] - abox[0],
|
||||
abox[3] - abox[1]);
|
||||
clipRegion.clipBoxToBounds(abox);
|
||||
if (abox[0] >= abox[2] || abox[1] >= abox[3]) {
|
||||
return;
|
||||
}
|
||||
sr.intersectClipBox(abox[0], abox[1], abox[2], abox[3]);
|
||||
context = startSequence(sg, s, devR, abox);
|
||||
|
||||
spanClipLoop(context, sr, clipRegion, abox);
|
||||
|
||||
} finally {
|
||||
if (context != null) {
|
||||
endSequence(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void spanClipLoop(Object ctx, SpanIterator sr,
|
||||
Region r, int[] abox) {
|
||||
if (!r.isRectangular()) {
|
||||
sr = r.filter(sr);
|
||||
}
|
||||
while (sr.nextSpan(abox)) {
|
||||
int x = abox[0];
|
||||
int y = abox[1];
|
||||
renderBox(ctx, x, y, abox[2] - x, abox[3] - y);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
jdkSrc/jdk8/sun/java2d/pipe/TextPipe.java
Normal file
49
jdkSrc/jdk8/sun/java2d/pipe/TextPipe.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2003, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Charlton Innovations, Inc.
|
||||
*/
|
||||
|
||||
package sun.java2d.pipe;
|
||||
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.TextLayout;
|
||||
|
||||
/**
|
||||
* This interface defines the set of calls that pipeline objects
|
||||
* can use to pass on responsibility for drawing various text
|
||||
* representations.
|
||||
*/
|
||||
public interface TextPipe {
|
||||
public void drawString(SunGraphics2D g2d, String s,
|
||||
double x, double y);
|
||||
public void drawGlyphVector(SunGraphics2D g2d, GlyphVector g,
|
||||
float x, float y);
|
||||
public void drawChars(SunGraphics2D g2d,
|
||||
char data[], int offset, int length,
|
||||
int x, int y);
|
||||
}
|
||||
98
jdkSrc/jdk8/sun/java2d/pipe/TextRenderer.java
Normal file
98
jdkSrc/jdk8/sun/java2d/pipe/TextRenderer.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2003, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Font;
|
||||
import java.awt.font.GlyphVector;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.FontInfo;
|
||||
import sun.font.GlyphList;
|
||||
|
||||
/*
|
||||
* This class uses the alpha graybits arrays from a GlyphList object to
|
||||
* drive a CompositePipe in much the same way as the antialiasing renderer.
|
||||
*/
|
||||
public class TextRenderer extends GlyphListPipe {
|
||||
|
||||
CompositePipe outpipe;
|
||||
|
||||
public TextRenderer(CompositePipe pipe) {
|
||||
outpipe = pipe;
|
||||
}
|
||||
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
|
||||
int num = gl.getNumGlyphs();
|
||||
Region clipRegion = sg2d.getCompClip();
|
||||
int cx1 = clipRegion.getLoX();
|
||||
int cy1 = clipRegion.getLoY();
|
||||
int cx2 = clipRegion.getHiX();
|
||||
int cy2 = clipRegion.getHiY();
|
||||
Object ctx = null;
|
||||
try {
|
||||
int[] bounds = gl.getBounds();
|
||||
Rectangle r = new Rectangle(bounds[0], bounds[1],
|
||||
bounds[2] - bounds[0],
|
||||
bounds[3] - bounds[1]);
|
||||
Shape s = sg2d.untransformShape(r);
|
||||
ctx = outpipe.startSequence(sg2d, s, r, bounds);
|
||||
for (int i = 0; i < num; i++) {
|
||||
gl.setGlyphIndex(i);
|
||||
int metrics[] = gl.getMetrics();
|
||||
int gx1 = metrics[0];
|
||||
int gy1 = metrics[1];
|
||||
int w = metrics[2];
|
||||
int gx2 = gx1 + w;
|
||||
int gy2 = gy1 + metrics[3];
|
||||
int off = 0;
|
||||
if (gx1 < cx1) {
|
||||
off = cx1 - gx1;
|
||||
gx1 = cx1;
|
||||
}
|
||||
if (gy1 < cy1) {
|
||||
off += (cy1 - gy1) * w;
|
||||
gy1 = cy1;
|
||||
}
|
||||
if (gx2 > cx2) gx2 = cx2;
|
||||
if (gy2 > cy2) gy2 = cy2;
|
||||
if (gx2 > gx1 && gy2 > gy1 &&
|
||||
outpipe.needTile(ctx, gx1, gy1, gx2 - gx1, gy2 - gy1))
|
||||
{
|
||||
byte alpha[] = gl.getGrayBits();
|
||||
outpipe.renderPathTile(ctx, alpha, off, w,
|
||||
gx1, gy1, gx2 - gx1, gy2 - gy1);
|
||||
} else {
|
||||
outpipe.skipTile(ctx, gx1, gy1);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (ctx != null) {
|
||||
outpipe.endSequence(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
241
jdkSrc/jdk8/sun/java2d/pipe/ValidatePipe.java
Normal file
241
jdkSrc/jdk8/sun/java2d/pipe/ValidatePipe.java
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2003, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.Color;
|
||||
import java.awt.Image;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ImageObserver;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import java.awt.font.GlyphVector;
|
||||
|
||||
/**
|
||||
* This class is used to force a revalidation of the pipelines of
|
||||
* the indicated SunGraphics2D object before a draw command.
|
||||
* After calling SunGraphics2D.validatePipe() to force the pipeline
|
||||
* to be revalidated, this object redispatches the draw command to
|
||||
* the new valid pipe object.
|
||||
*/
|
||||
public class ValidatePipe
|
||||
implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, TextPipe,
|
||||
DrawImagePipe
|
||||
{
|
||||
/*
|
||||
* Different subclasses may override this to do various
|
||||
* other forms of validation and return a return code
|
||||
* indicating whether or not the validation was successful.
|
||||
*/
|
||||
public boolean validate(SunGraphics2D sg) {
|
||||
sg.validatePipe();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void drawLine(SunGraphics2D sg,
|
||||
int x1, int y1, int x2, int y2) {
|
||||
if (validate(sg)) {
|
||||
sg.drawpipe.drawLine(sg, x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height) {
|
||||
if (validate(sg)) {
|
||||
sg.drawpipe.drawRect(sg, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height) {
|
||||
if (validate(sg)) {
|
||||
sg.fillpipe.fillRect(sg, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawRoundRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight) {
|
||||
if (validate(sg)) {
|
||||
sg.drawpipe.drawRoundRect(sg, x, y, width, height,
|
||||
arcWidth, arcHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillRoundRect(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int arcWidth, int arcHeight) {
|
||||
if (validate(sg)) {
|
||||
sg.fillpipe.fillRoundRect(sg, x, y, width, height,
|
||||
arcWidth, arcHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawOval(SunGraphics2D sg,
|
||||
int x, int y, int width, int height) {
|
||||
if (validate(sg)) {
|
||||
sg.drawpipe.drawOval(sg, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillOval(SunGraphics2D sg,
|
||||
int x, int y, int width, int height) {
|
||||
if (validate(sg)) {
|
||||
sg.fillpipe.fillOval(sg, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawArc(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle) {
|
||||
if (validate(sg)) {
|
||||
sg.drawpipe.drawArc(sg, x, y, width, height, startAngle, arcAngle);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillArc(SunGraphics2D sg,
|
||||
int x, int y, int width, int height,
|
||||
int startAngle, int arcAngle) {
|
||||
if (validate(sg)) {
|
||||
sg.fillpipe.fillArc(sg, x, y, width, height, startAngle, arcAngle);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawPolyline(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints) {
|
||||
if (validate(sg)) {
|
||||
sg.drawpipe.drawPolyline(sg, xPoints, yPoints, nPoints);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawPolygon(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints) {
|
||||
if (validate(sg)) {
|
||||
sg.drawpipe.drawPolygon(sg, xPoints, yPoints, nPoints);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillPolygon(SunGraphics2D sg,
|
||||
int xPoints[], int yPoints[],
|
||||
int nPoints) {
|
||||
if (validate(sg)) {
|
||||
sg.fillpipe.fillPolygon(sg, xPoints, yPoints, nPoints);
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(SunGraphics2D sg, Shape s) {
|
||||
if (validate(sg)) {
|
||||
sg.shapepipe.draw(sg, s);
|
||||
}
|
||||
}
|
||||
|
||||
public void fill(SunGraphics2D sg, Shape s) {
|
||||
if (validate(sg)) {
|
||||
sg.shapepipe.fill(sg, s);
|
||||
}
|
||||
}
|
||||
public void drawString(SunGraphics2D sg, String s, double x, double y) {
|
||||
if (validate(sg)) {
|
||||
sg.textpipe.drawString(sg, s, x, y);
|
||||
}
|
||||
}
|
||||
public void drawGlyphVector(SunGraphics2D sg, GlyphVector g,
|
||||
float x, float y) {
|
||||
if (validate(sg)) {
|
||||
sg.textpipe.drawGlyphVector(sg, g, x, y);
|
||||
}
|
||||
}
|
||||
public void drawChars(SunGraphics2D sg,
|
||||
char data[], int offset, int length,
|
||||
int x, int y) {
|
||||
if (validate(sg)) {
|
||||
sg.textpipe.drawChars(sg, data, offset, length, x, y);
|
||||
}
|
||||
}
|
||||
public boolean copyImage(SunGraphics2D sg, Image img,
|
||||
int x, int y,
|
||||
Color bgColor,
|
||||
ImageObserver observer) {
|
||||
if (validate(sg)) {
|
||||
return sg.imagepipe.copyImage(sg, img, x, y, bgColor, observer);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean copyImage(SunGraphics2D sg, Image img,
|
||||
int dx, int dy, int sx, int sy, int w, int h,
|
||||
Color bgColor,
|
||||
ImageObserver observer) {
|
||||
if (validate(sg)) {
|
||||
return sg.imagepipe.copyImage(sg, img, dx, dy, sx, sy, w, h,
|
||||
bgColor, observer);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean scaleImage(SunGraphics2D sg, Image img, int x, int y,
|
||||
int w, int h,
|
||||
Color bgColor,
|
||||
ImageObserver observer) {
|
||||
if (validate(sg)) {
|
||||
return sg.imagepipe.scaleImage(sg, img, x, y, w, h, bgColor,
|
||||
observer);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean scaleImage(SunGraphics2D sg, Image img,
|
||||
int dx1, int dy1, int dx2, int dy2,
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
Color bgColor,
|
||||
ImageObserver observer) {
|
||||
if (validate(sg)) {
|
||||
return sg.imagepipe.scaleImage(sg, img, dx1, dy1, dx2, dy2,
|
||||
sx1, sy1, sx2, sy2, bgColor,
|
||||
observer);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean transformImage(SunGraphics2D sg, Image img,
|
||||
AffineTransform atfm,
|
||||
ImageObserver observer) {
|
||||
if (validate(sg)) {
|
||||
return sg.imagepipe.transformImage(sg, img, atfm, observer);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public void transformImage(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp op, int x, int y) {
|
||||
if (validate(sg)) {
|
||||
sg.imagepipe.transformImage(sg, img, op, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelDeviceEventListener.java
Normal file
59
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelDeviceEventListener.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.hw;
|
||||
|
||||
/**
|
||||
* An interface for receiving notifications about imminent accelerated device's
|
||||
* events. Upon receiving such event appropriate actions can be taken (for
|
||||
* example, resources associated with the device can be freed).
|
||||
*/
|
||||
public interface AccelDeviceEventListener {
|
||||
/**
|
||||
* Called when the device is about to be reset.
|
||||
*
|
||||
* One must release all native resources associated with the device which
|
||||
* prevent the device from being reset (such as Default Pool resources for
|
||||
* the D3D pipeline).
|
||||
*
|
||||
* It is safe to remove the listener while in the call back.
|
||||
*
|
||||
* Note: this method is called on the rendering thread,
|
||||
* do not call into user code, do not take RQ lock!
|
||||
*/
|
||||
public void onDeviceReset();
|
||||
|
||||
/**
|
||||
* Called when the device is about to be disposed of.
|
||||
*
|
||||
* One must release all native resources associated with the device.
|
||||
*
|
||||
* It is safe to remove the listener while in the call back.
|
||||
*
|
||||
* Note: this method is called on the rendering thread,
|
||||
* do not call into user code, do not take RQ lock!
|
||||
*/
|
||||
public void onDeviceDispose();
|
||||
}
|
||||
169
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java
Normal file
169
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelDeviceEventNotifier.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.hw;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
|
||||
/**
|
||||
* This class is used to notify listeners about accelerated device's
|
||||
* events such as device reset or dispose that are about to occur.
|
||||
*/
|
||||
public class AccelDeviceEventNotifier {
|
||||
|
||||
private static AccelDeviceEventNotifier theInstance;
|
||||
|
||||
/**
|
||||
* A device is about to be reset. The listeners have to release all
|
||||
* resources associated with the device which are required for the device
|
||||
* to be reset.
|
||||
*/
|
||||
@Native public static final int DEVICE_RESET = 0;
|
||||
|
||||
/**
|
||||
* A device is about to be disposed. The listeners have to release all
|
||||
* resources associated with the device.
|
||||
*/
|
||||
@Native public static final int DEVICE_DISPOSED = 1;
|
||||
|
||||
private final Map<AccelDeviceEventListener, Integer> listeners;
|
||||
|
||||
private AccelDeviceEventNotifier() {
|
||||
listeners = Collections.synchronizedMap(
|
||||
new HashMap<AccelDeviceEventListener, Integer>(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a singleton of AccelDeviceEventNotifier if it exists. If the
|
||||
* passed boolean is false and singleton doesn't exist yet, null is
|
||||
* returned. If the passed boolean is {@code true} and singleton doesn't
|
||||
* exist it will be created and returned.
|
||||
*
|
||||
* @param create whether to create a singleton instance if doesn't yet
|
||||
* exist
|
||||
* @return a singleton instance or null
|
||||
*/
|
||||
private static synchronized
|
||||
AccelDeviceEventNotifier getInstance(boolean create)
|
||||
{
|
||||
if (theInstance == null && create) {
|
||||
theInstance = new AccelDeviceEventNotifier();
|
||||
}
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to indicate that a device event had occurred.
|
||||
* If a singleton exists, the listeners (those associated with
|
||||
* the device) will be notified.
|
||||
*
|
||||
* @param screen a screen number of the device which is a source of
|
||||
* the event
|
||||
* @param eventType a type of the event
|
||||
* @see #DEVICE_DISPOSED
|
||||
* @see #DEVICE_RESET
|
||||
*/
|
||||
public static final void eventOccured(int screen, int eventType) {
|
||||
AccelDeviceEventNotifier notifier = getInstance(false);
|
||||
if (notifier != null) {
|
||||
notifier.notifyListeners(eventType, screen);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the listener associated with a device on particular screen.
|
||||
*
|
||||
* Note: the listener must be removed as otherwise it will forever
|
||||
* be referenced by the notifier.
|
||||
*
|
||||
* @param l the listener
|
||||
* @param screen the screen number indicating which device the listener is
|
||||
* interested in.
|
||||
*/
|
||||
public static final void addListener(AccelDeviceEventListener l,int screen){
|
||||
getInstance(true).add(l, screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the listener.
|
||||
*
|
||||
* @param l the listener
|
||||
*/
|
||||
public static final void removeListener(AccelDeviceEventListener l) {
|
||||
getInstance(true).remove(l);
|
||||
}
|
||||
|
||||
private final void add(AccelDeviceEventListener theListener, int screen) {
|
||||
listeners.put(theListener, screen);
|
||||
}
|
||||
private final void remove(AccelDeviceEventListener theListener) {
|
||||
listeners.remove(theListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the listeners associated with the screen's device about the
|
||||
* event.
|
||||
*
|
||||
* Implementation note: the current list of listeners is first duplicated
|
||||
* which allows the listeners to remove themselves during the iteration.
|
||||
*
|
||||
* @param screen a screen number with which the device which is a source of
|
||||
* the event is associated with
|
||||
* @param eventType a type of the event
|
||||
* @see #DEVICE_DISPOSED
|
||||
* @see #DEVICE_RESET
|
||||
*/
|
||||
private final void notifyListeners(int deviceEventType, int screen) {
|
||||
HashMap<AccelDeviceEventListener, Integer> listClone;
|
||||
Set<AccelDeviceEventListener> cloneSet;
|
||||
|
||||
synchronized(listeners) {
|
||||
listClone =
|
||||
new HashMap<AccelDeviceEventListener, Integer>(listeners);
|
||||
}
|
||||
|
||||
cloneSet = listClone.keySet();
|
||||
Iterator<AccelDeviceEventListener> itr = cloneSet.iterator();
|
||||
while (itr.hasNext()) {
|
||||
AccelDeviceEventListener current = itr.next();
|
||||
Integer i = listClone.get(current);
|
||||
// only notify listeners which are interested in this device
|
||||
if (i != null && i.intValue() != screen) {
|
||||
continue;
|
||||
}
|
||||
if (deviceEventType == DEVICE_RESET) {
|
||||
current.onDeviceReset();
|
||||
} else if (deviceEventType == DEVICE_DISPOSED) {
|
||||
current.onDeviceDispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
95
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelGraphicsConfig.java
Normal file
95
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelGraphicsConfig.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.hw;
|
||||
|
||||
import java.awt.image.VolatileImage;
|
||||
|
||||
/**
|
||||
* Implementors of this interface provida a way to create a
|
||||
* {@code VolatileImage} whose destination surface is an
|
||||
* {@link AccelSurface} of specified type.
|
||||
*
|
||||
* @see AccelSurface
|
||||
*/
|
||||
public interface AccelGraphicsConfig extends BufferedContextProvider {
|
||||
/**
|
||||
* Returns a VolatileImage with specified width, height, transparency
|
||||
* and guaranteed accelerated surface type. If such image can not be created
|
||||
* (out of vram error, specific surface type is not supported) null
|
||||
* is returned.
|
||||
*
|
||||
* Note: if {@link AccelSurface#TEXTURE} type is requested, rendering
|
||||
* to the image will be denied by throwing
|
||||
* {@code UnsupportedOperationException }
|
||||
* from {@link java.awt.image.VolatileImage#getGraphics} and
|
||||
* {@link java.awt.image.VolatileImage#createGraphics}
|
||||
*
|
||||
* @param width the width of the returned {@code VolatileImage}
|
||||
* @param height the height of the returned {@code VolatileImage}
|
||||
* @param transparency the specified transparency mode
|
||||
* @param type requested accelerated surface type as specified by constants
|
||||
* in AccelSurface interface
|
||||
* @return a {@code VolatileImage} backed up by requested accelerated
|
||||
* surface type or null
|
||||
* @throws IllegalArgumentException if the transparency is not a valid value
|
||||
* @see AccelSurface#TEXTURE
|
||||
* @see AccelSurface#RT_PLAIN
|
||||
* @see AccelSurface#RT_TEXTURE
|
||||
*/
|
||||
public VolatileImage createCompatibleVolatileImage(int width, int height,
|
||||
int transparency,
|
||||
int type);
|
||||
/**
|
||||
* Returns object representing capabilities of the context associated
|
||||
* with this {@code AccelGraphicsConfig}.
|
||||
*
|
||||
* @return ContextCapabilities object representing caps
|
||||
* @see ContextCapabilities
|
||||
*/
|
||||
public ContextCapabilities getContextCapabilities();
|
||||
|
||||
/**
|
||||
* Adds an {@code AccelDeviceEventListener} to listen to accelerated
|
||||
* device's (which is associated with this {@code AccelGraphicsConfig})
|
||||
* events.
|
||||
*
|
||||
* Note: a hard link to the listener may be kept so it must be explicitly
|
||||
* removed via {@link #removeDeviceEventListener()}.
|
||||
*
|
||||
* @param l the listener
|
||||
* @see AccelDeviceEventListener
|
||||
*/
|
||||
public void addDeviceEventListener(AccelDeviceEventListener l);
|
||||
|
||||
/**
|
||||
* Removes an {@code AccelDeviceEventListener} from the list of listeners
|
||||
* for this device's events.
|
||||
*
|
||||
* @param l the listener
|
||||
* @see AccelDeviceEventListener
|
||||
*/
|
||||
public void removeDeviceEventListener(AccelDeviceEventListener l);
|
||||
}
|
||||
137
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelSurface.java
Normal file
137
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelSurface.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.hw;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import sun.java2d.Surface;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
/**
|
||||
* Abstraction for a hardware accelerated surface.
|
||||
*/
|
||||
public interface AccelSurface extends BufferedContextProvider, Surface {
|
||||
/**
|
||||
* Undefined
|
||||
*/
|
||||
@Native public static final int UNDEFINED = 0;
|
||||
/**
|
||||
* Window (or window substitute) surface
|
||||
*/
|
||||
@Native public static final int WINDOW = 1;
|
||||
/**
|
||||
* Render-To Plain surface (Render Target surface for Direct3D)
|
||||
*/
|
||||
@Native public static final int RT_PLAIN = 2;
|
||||
/**
|
||||
* Texture surface
|
||||
*/
|
||||
@Native public static final int TEXTURE = 3;
|
||||
/**
|
||||
* A back-buffer surface (SwapChain surface for Direct3D, backbuffer for
|
||||
* OpenGL)
|
||||
*/
|
||||
@Native public static final int FLIP_BACKBUFFER = 4;
|
||||
/**
|
||||
* Render-To Texture surface (fbobject for OpenGL, texture with render-to
|
||||
* attribute for Direct3D)
|
||||
*/
|
||||
@Native public static final int RT_TEXTURE = 5;
|
||||
|
||||
/**
|
||||
* Returns {@code int} representing surface's type as defined by constants
|
||||
* in this interface.
|
||||
*
|
||||
* @return an integer representing this surface's type
|
||||
* @see AccelSurface#UNDEFINED
|
||||
* @see AccelSurface#WINDOW
|
||||
* @see AccelSurface#RT_PLAIN
|
||||
* @see AccelSurface#TEXTURE
|
||||
* @see AccelSurface#FLIP_BACKBUFFER
|
||||
* @see AccelSurface#RT_TEXTURE
|
||||
*/
|
||||
public int getType();
|
||||
|
||||
/**
|
||||
* Returns a pointer to the native surface data associated with this
|
||||
* surface.
|
||||
* Note: this pointer is only valid on the rendering thread.
|
||||
*
|
||||
* @return pointer to the native surface's data
|
||||
*/
|
||||
public long getNativeOps();
|
||||
|
||||
/**
|
||||
* Returns a pointer to the real native resource
|
||||
* of the specified type associated with this AccelSurface.
|
||||
* Note: this pointer is only valid on the rendering thread.
|
||||
*
|
||||
* @param resType the type of the requested resource
|
||||
* @return a long containing a pointer to the native resource of the
|
||||
* specified type or 0L if such resource doesn't exist for this surface
|
||||
*/
|
||||
public long getNativeResource(int resType);
|
||||
|
||||
/**
|
||||
* Marks this surface dirty.
|
||||
*/
|
||||
public void markDirty();
|
||||
|
||||
/**
|
||||
* Returns whether the pipeline considers this surface valid. A surface
|
||||
* may become invalid if it is disposed of, or resized.
|
||||
*
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
public boolean isValid();
|
||||
|
||||
/**
|
||||
* Returns whether this surface is lost. The return value is only valid
|
||||
* on the render thread, meaning that even if this method returns
|
||||
* {@code true} it could be lost in the next moment unless it is called
|
||||
* on the rendering thread.
|
||||
*
|
||||
* @return true if the surface is known to be lost, false otherwise
|
||||
*/
|
||||
public boolean isSurfaceLost();
|
||||
|
||||
/**
|
||||
* Returns the requested bounds of the destination surface. The real bounds
|
||||
* of the native accelerated surface may differ. Use
|
||||
* {@link #getNativeBounds} to get the bounds of the native surface.
|
||||
*
|
||||
* @return Rectangle representing java surface's bounds
|
||||
*/
|
||||
public Rectangle getBounds();
|
||||
|
||||
/**
|
||||
* Returns real bounds of the native surface, which may differ from those
|
||||
* returned by {@link #getBounds}.
|
||||
*
|
||||
* @return Rectangle representing native surface's bounds
|
||||
*/
|
||||
public Rectangle getNativeBounds();
|
||||
}
|
||||
74
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelTypedVolatileImage.java
Normal file
74
jdkSrc/jdk8/sun/java2d/pipe/hw/AccelTypedVolatileImage.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.hw;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.*;
|
||||
|
||||
/**
|
||||
* This is an image with forced type of the accelerated surface.
|
||||
*/
|
||||
public class AccelTypedVolatileImage extends SunVolatileImage {
|
||||
|
||||
/**
|
||||
* Creates a volatile image with specified type of accelerated surface.
|
||||
*
|
||||
* @param graphicsConfig a GraphicsConfiguration for which this image should
|
||||
* be created.
|
||||
* @param width width
|
||||
* @param height width
|
||||
* @param transparency type of {@link java.awt.Transparency transparency}
|
||||
* requested for the image
|
||||
* @param accType type of the desired accelerated surface as defined in
|
||||
* AccelSurface interface
|
||||
* @see sun.java2d.pipe.hw.AccelSurface
|
||||
*/
|
||||
public AccelTypedVolatileImage(GraphicsConfiguration graphicsConfig,
|
||||
int width, int height, int transparency,
|
||||
int accType)
|
||||
{
|
||||
super(null, graphicsConfig, width, height, null, transparency,
|
||||
null, accType);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* This method will throw {@code UnsupportedOperationException} if it this
|
||||
* image's destination surface can not be rendered to.
|
||||
*/
|
||||
@Override
|
||||
public Graphics2D createGraphics() {
|
||||
if (getForcedAccelSurfaceType() == TEXTURE) {
|
||||
throw new UnsupportedOperationException("Can't render " +
|
||||
"to a non-RT Texture");
|
||||
}
|
||||
return super.createGraphics();
|
||||
}
|
||||
}
|
||||
45
jdkSrc/jdk8/sun/java2d/pipe/hw/BufferedContextProvider.java
Normal file
45
jdkSrc/jdk8/sun/java2d/pipe/hw/BufferedContextProvider.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.hw;
|
||||
|
||||
import sun.java2d.pipe.BufferedContext;
|
||||
|
||||
/**
|
||||
* Classes implementing this interface can provide the {@code BufferedContext}
|
||||
* associated with or used by them.
|
||||
*
|
||||
* @see sun.java2d.pipe.BufferedContext
|
||||
*/
|
||||
public interface BufferedContextProvider {
|
||||
/**
|
||||
* Retrieves a context associated with object implementing this
|
||||
* interface.
|
||||
*
|
||||
* @return associated context
|
||||
* @see sun.java2d.pipe.BufferedContext
|
||||
*/
|
||||
public BufferedContext getContext();
|
||||
}
|
||||
129
jdkSrc/jdk8/sun/java2d/pipe/hw/ContextCapabilities.java
Normal file
129
jdkSrc/jdk8/sun/java2d/pipe/hw/ContextCapabilities.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.hw;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a set of capabilities of a BufferedContext and associated
|
||||
* AccelGraphicsConfig.
|
||||
*
|
||||
* @see AccelGraphicsConfig
|
||||
*/
|
||||
public class ContextCapabilities {
|
||||
/** Indicates that the context has no capabilities. */
|
||||
public static final int CAPS_EMPTY = (0 << 0);
|
||||
/** Indicates that the context supports RT surfaces with alpha channel. */
|
||||
public static final int CAPS_RT_PLAIN_ALPHA = (1 << 1);
|
||||
/** Indicates that the context supports RT textures with alpha channel. */
|
||||
public static final int CAPS_RT_TEXTURE_ALPHA = (1 << 2);
|
||||
/** Indicates that the context supports opaque RT textures. */
|
||||
public static final int CAPS_RT_TEXTURE_OPAQUE = (1 << 3);
|
||||
/** Indicates that the context supports multitexturing. */
|
||||
public static final int CAPS_MULTITEXTURE = (1 << 4);
|
||||
/** Indicates that the context supports non-pow2 texture dimensions. */
|
||||
public static final int CAPS_TEXNONPOW2 = (1 << 5);
|
||||
/** Indicates that the context supports non-square textures. */
|
||||
public static final int CAPS_TEXNONSQUARE = (1 << 6);
|
||||
/** Indicates that the context supports pixel shader 2.0 or better. */
|
||||
public static final int CAPS_PS20 = (1 << 7);
|
||||
/** Indicates that the context supports pixel shader 3.0 or better. */
|
||||
public static final int CAPS_PS30 = (1 << 8);
|
||||
/*
|
||||
* Pipeline contexts should use this for defining pipeline-specific
|
||||
* capabilities, for example:
|
||||
* int CAPS_D3D_1 = (FIRST_PRIVATE_CAP << 0);
|
||||
* int CAPS_D3D_2 = (FIRST_PRIVATE_CAP << 1);
|
||||
*/
|
||||
protected static final int FIRST_PRIVATE_CAP = (1 << 16);
|
||||
|
||||
protected final int caps;
|
||||
protected final String adapterId;
|
||||
|
||||
/**
|
||||
* Constructs a {@code ContextCapabilities} object.
|
||||
* @param caps an {@code int} representing the capabilities
|
||||
* @param a {@code String} representing the name of the adapter, or null,
|
||||
* in which case the adapterId will be set to "unknown adapter".
|
||||
*/
|
||||
protected ContextCapabilities(int caps, String adapterId) {
|
||||
this.caps = caps;
|
||||
this.adapterId = adapterId != null ? adapterId : "unknown adapter";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the name of the graphics adapter if such
|
||||
* could be determined. It is guaranteed to never return {@code null}.
|
||||
* @return string representing adapter id
|
||||
*/
|
||||
public String getAdapterId() {
|
||||
return adapterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code int} with capabilities (OR-ed constants defined in
|
||||
* this class and its pipeline-specific subclasses).
|
||||
* @return capabilities as {@code int}
|
||||
*/
|
||||
public int getCaps() {
|
||||
return caps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buf =
|
||||
new StringBuffer("ContextCapabilities: adapter=" +
|
||||
adapterId+", caps=");
|
||||
if (caps == CAPS_EMPTY) {
|
||||
buf.append("CAPS_EMPTY");
|
||||
} else {
|
||||
if ((caps & CAPS_RT_PLAIN_ALPHA) != 0) {
|
||||
buf.append("CAPS_RT_PLAIN_ALPHA|");
|
||||
}
|
||||
if ((caps & CAPS_RT_TEXTURE_ALPHA) != 0) {
|
||||
buf.append("CAPS_RT_TEXTURE_ALPHA|");
|
||||
}
|
||||
if ((caps & CAPS_RT_TEXTURE_OPAQUE) != 0) {
|
||||
buf.append("CAPS_RT_TEXTURE_OPAQUE|");
|
||||
}
|
||||
if ((caps & CAPS_MULTITEXTURE) != 0) {
|
||||
buf.append("CAPS_MULTITEXTURE|");
|
||||
}
|
||||
if ((caps & CAPS_TEXNONPOW2) != 0) {
|
||||
buf.append("CAPS_TEXNONPOW2|");
|
||||
}
|
||||
if ((caps & CAPS_TEXNONSQUARE) != 0) {
|
||||
buf.append("CAPS_TEXNONSQUARE|");
|
||||
}
|
||||
if ((caps & CAPS_PS20) != 0) {
|
||||
buf.append("CAPS_PS20|");
|
||||
}
|
||||
if ((caps & CAPS_PS30) != 0) {
|
||||
buf.append("CAPS_PS30|");
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
154
jdkSrc/jdk8/sun/java2d/pipe/hw/ExtendedBufferCapabilities.java
Normal file
154
jdkSrc/jdk8/sun/java2d/pipe/hw/ExtendedBufferCapabilities.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* 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.hw;
|
||||
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.ImageCapabilities;
|
||||
|
||||
/**
|
||||
* Provides extended BufferStrategy capabilities, allowing to specify
|
||||
* the type of vertical refresh synchronization for a buffer strategy.
|
||||
*
|
||||
* This BS capability is always page flipping because v-sync is only relevant
|
||||
* to flipping buffer strategies.
|
||||
*
|
||||
* Note that asking for a v-synced BS doesn't necessarily guarantee that it will
|
||||
* be v-synced since the vsync capability may be disabled in the driver, or
|
||||
* there may be other restriction (like a number of v-synced buffer strategies
|
||||
* allowed per vm). Because of this {@code createBufferStrategy} doesn't
|
||||
* throw {@code AWTException} when a v-synced BS could not be created when
|
||||
* requested.
|
||||
*
|
||||
* @see java.awt.Canvas#createBufferStrategy(int, BufferCapabilities)
|
||||
* @see java.awt.Window#createBufferStrategy(int, BufferCapabilities)
|
||||
*/
|
||||
public class ExtendedBufferCapabilities extends BufferCapabilities {
|
||||
|
||||
/**
|
||||
* Type of synchronization on vertical retrace.
|
||||
*/
|
||||
public static enum VSyncType {
|
||||
/**
|
||||
* Use the default v-sync mode appropriate for given BufferStrategy
|
||||
* and situation.
|
||||
*/
|
||||
VSYNC_DEFAULT(0),
|
||||
|
||||
/**
|
||||
* Synchronize flip on vertical retrace.
|
||||
*/
|
||||
VSYNC_ON(1),
|
||||
|
||||
/**
|
||||
* Do not synchronize flip on vertical retrace.
|
||||
*/
|
||||
VSYNC_OFF(2);
|
||||
|
||||
/**
|
||||
* Used to identify the v-sync type (independent of the constants
|
||||
* order as opposed to {@code ordinal()}).
|
||||
*/
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private VSyncType(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
private int id;
|
||||
}
|
||||
|
||||
private VSyncType vsync;
|
||||
|
||||
/**
|
||||
* Creates an ExtendedBufferCapabilities object with front/back/flip caps
|
||||
* from the passed cap, and VSYNC_DEFAULT v-sync mode.
|
||||
*/
|
||||
public ExtendedBufferCapabilities(BufferCapabilities caps) {
|
||||
super(caps.getFrontBufferCapabilities(),
|
||||
caps.getBackBufferCapabilities(),
|
||||
caps.getFlipContents());
|
||||
|
||||
this.vsync = VSyncType.VSYNC_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExtendedBufferCapabilities instance with front/back/flip caps
|
||||
* from the passed caps, and VSYNC_DEFAULT v-sync mode.
|
||||
*/
|
||||
public ExtendedBufferCapabilities(ImageCapabilities front,
|
||||
ImageCapabilities back, FlipContents flip)
|
||||
{
|
||||
super(front, back, flip);
|
||||
|
||||
this.vsync = VSyncType.VSYNC_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExtendedBufferCapabilities instance with front/back/flip caps
|
||||
* from the passed image/flip caps, and the v-sync type.
|
||||
*/
|
||||
public ExtendedBufferCapabilities(ImageCapabilities front,
|
||||
ImageCapabilities back, FlipContents flip,
|
||||
VSyncType t)
|
||||
{
|
||||
super(front, back, flip);
|
||||
|
||||
this.vsync = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExtendedBufferCapabilities instance with front/back/flip caps
|
||||
* from the passed cap, and the passed v-sync mode.
|
||||
*/
|
||||
public ExtendedBufferCapabilities(BufferCapabilities caps, VSyncType t) {
|
||||
super(caps.getFrontBufferCapabilities(),
|
||||
caps.getBackBufferCapabilities(),
|
||||
caps.getFlipContents());
|
||||
|
||||
this.vsync = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExtendedBufferCapabilities instance with front/back/flip caps
|
||||
* from the object, and passed v-sync mode.
|
||||
*/
|
||||
public ExtendedBufferCapabilities derive(VSyncType t) {
|
||||
return new ExtendedBufferCapabilities(this, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of v-sync requested by this capabilities instance.
|
||||
*/
|
||||
public VSyncType getVSync() {
|
||||
return vsync;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isPageFlipping() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user