@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 AATileGenerator getAATileGenerator(double x, double y, double dx1, double dy1, double dx2, double dy2, double lw1, double lw2, Region clip, int bbox[]) { // REMIND: Deal with large coordinates! double ldx1, ldy1, ldx2, ldy2; boolean innerpgram = (lw1 > 0 && lw2 > 0); if (innerpgram) { ldx1 = dx1 * lw1; ldy1 = dy1 * lw1; ldx2 = dx2 * lw2; ldy2 = dy2 * lw2; x -= (ldx1 + ldx2) / 2.0; y -= (ldy1 + ldy2) / 2.0; dx1 += ldx1; dy1 += ldy1; dx2 += ldx2; dy2 += ldy2; if (lw1 > 1 && lw2 > 1) { // Inner parallelogram was entirely consumed by stroke... innerpgram = false; } } else { ldx1 = ldy1 = ldx2 = ldy2 = 0; } Renderer r = new Renderer(3, 3, clip.getLoX(), clip.getLoY(), clip.getWidth(), clip.getHeight(), PathIterator.WIND_EVEN_ODD); r.moveTo((float) x, (float) y); r.lineTo((float) (x+dx1), (float) (y+dy1)); r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.lineTo((float) (x+dx2), (float) (y+dy2)); r.closePath(); if (innerpgram) { x += ldx1 + ldx2; y += ldy1 + ldy2; dx1 -= 2.0 * ldx1; dy1 -= 2.0 * ldy1; dx2 -= 2.0 * ldx2; dy2 -= 2.0 * ldy2; r.moveTo((float) x, (float) y); r.lineTo((float) (x+dx1), (float) (y+dy1)); r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.lineTo((float) (x+dx2), (float) (y+dy2)); r.closePath(); } r.pathDone(); r.endRendering(); PiscesTileGenerator ptg = new PiscesTileGenerator(r, r.MAX_AA_ALPHA); ptg.getBbox(bbox); return ptg; }
/** * {@inheritDoc} */ @Override public AATileGenerator getAATileGenerator(double x, double y, double dx1, double dy1, double dx2, double dy2, double lw1, double lw2, Region clip, int bbox[]) { // REMIND: Deal with large coordinates! double ldx1, ldy1, ldx2, ldy2; boolean innerpgram = (lw1 > 0 && lw2 > 0); if (innerpgram) { ldx1 = dx1 * lw1; ldy1 = dy1 * lw1; ldx2 = dx2 * lw2; ldy2 = dy2 * lw2; x -= (ldx1 + ldx2) / 2.0; y -= (ldy1 + ldy2) / 2.0; dx1 += ldx1; dy1 += ldy1; dx2 += ldx2; dy2 += ldy2; if (lw1 > 1 && lw2 > 1) { // Inner parallelogram was entirely consumed by stroke... innerpgram = false; } } else { ldx1 = ldy1 = ldx2 = ldy2 = 0; } Rasterizer r = getRasterizer(); r.setUsage(Rasterizer.EOFILL); r.beginPath(); r.beginSubpath((float) x, (float) y); r.appendLine((float) (x+dx1), (float) (y+dy1)); r.appendLine((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.appendLine((float) (x+dx2), (float) (y+dy2)); r.closedSubpath(); if (innerpgram) { x += ldx1 + ldx2; y += ldy1 + ldy2; dx1 -= 2.0 * ldx1; dy1 -= 2.0 * ldy1; dx2 -= 2.0 * ldx2; dy2 -= 2.0 * ldy2; r.beginSubpath((float) x, (float) y); r.appendLine((float) (x+dx1), (float) (y+dy1)); r.appendLine((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.appendLine((float) (x+dx2), (float) (y+dy2)); r.closedSubpath(); } try { r.endPath(); r.getAlphaBox(bbox); clip.clipBoxToBounds(bbox); if (bbox[0] >= bbox[2] || bbox[1] >= bbox[3]) { dropRasterizer(r); return null; } r.setOutputArea(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]); } catch (PRException e) { /* * This exeption is thrown from the native part of the Ductus * (only in case of a debug build) to indicate that some * segments of the path have very large coordinates. * See 4485298 for more info. */ System.err.println("DuctusRenderingEngine.getAATileGenerator: "+e); } return r; }
@Override public final AATileGenerator getAATileGenerator(double x, double y, double dx1, double dy1, double dx2, double dy2, double lw1, double lw2, Region clip, int[] bbox) { // REMIND: Deal with large coordinates! double ldx1, ldy1, ldx2, ldy2; boolean innerpgram = (lw1 > 0.0d && lw2 > 0.0d); if (innerpgram) { ldx1 = dx1 * lw1; ldy1 = dy1 * lw1; ldx2 = dx2 * lw2; ldy2 = dy2 * lw2; x -= (ldx1 + ldx2) / 2.0d; y -= (ldy1 + ldy2) / 2.0d; dx1 += ldx1; dy1 += ldy1; dx2 += ldx2; dy2 += ldy2; if (lw1 > 1.0d && lw2 > 1.0d) { // Inner parallelogram was entirely consumed by stroke... innerpgram = false; } } else { ldx1 = ldy1 = ldx2 = ldy2 = 0.0d; } MarlinTileGenerator ptg = null; DRenderer r = null; final DRendererContext rdrCtx = getRendererContext(); try { r = rdrCtx.renderer.init(clip.getLoX(), clip.getLoY(), clip.getWidth(), clip.getHeight(), DRenderer.WIND_EVEN_ODD); r.moveTo( x, y); r.lineTo( (x+dx1), (y+dy1)); r.lineTo( (x+dx1+dx2), (y+dy1+dy2)); r.lineTo( (x+dx2), (y+dy2)); r.closePath(); if (innerpgram) { x += ldx1 + ldx2; y += ldy1 + ldy2; dx1 -= 2.0d * ldx1; dy1 -= 2.0d * ldy1; dx2 -= 2.0d * ldx2; dy2 -= 2.0d * ldy2; r.moveTo( x, y); r.lineTo( (x+dx1), (y+dy1)); r.lineTo( (x+dx1+dx2), (y+dy1+dy2)); r.lineTo( (x+dx2), (y+dy2)); r.closePath(); } r.pathDone(); if (r.endRendering()) { ptg = rdrCtx.ptg.init(); ptg.getBbox(bbox); // note: do not returnRendererContext(rdrCtx) // as it will be called later by MarlinTileGenerator.dispose() r = null; } } finally { if (r != null) { // dispose renderer and recycle the RendererContext instance: r.dispose(); } } // Return null to cancel AA tile generation (nothing to render) return ptg; }
@Override public final AATileGenerator getAATileGenerator(double x, double y, double dx1, double dy1, double dx2, double dy2, double lw1, double lw2, Region clip, int[] bbox) { // REMIND: Deal with large coordinates! double ldx1, ldy1, ldx2, ldy2; boolean innerpgram = (lw1 > 0.0d && lw2 > 0.0d); if (innerpgram) { ldx1 = dx1 * lw1; ldy1 = dy1 * lw1; ldx2 = dx2 * lw2; ldy2 = dy2 * lw2; x -= (ldx1 + ldx2) / 2.0d; y -= (ldy1 + ldy2) / 2.0d; dx1 += ldx1; dy1 += ldy1; dx2 += ldx2; dy2 += ldy2; if (lw1 > 1.0d && lw2 > 1.0d) { // Inner parallelogram was entirely consumed by stroke... innerpgram = false; } } else { ldx1 = ldy1 = ldx2 = ldy2 = 0.0d; } MarlinTileGenerator ptg = null; Renderer r = null; final RendererContext rdrCtx = getRendererContext(); try { r = rdrCtx.renderer.init(clip.getLoX(), clip.getLoY(), clip.getWidth(), clip.getHeight(), Renderer.WIND_EVEN_ODD); r.moveTo((float) x, (float) y); r.lineTo((float) (x+dx1), (float) (y+dy1)); r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.lineTo((float) (x+dx2), (float) (y+dy2)); r.closePath(); if (innerpgram) { x += ldx1 + ldx2; y += ldy1 + ldy2; dx1 -= 2.0d * ldx1; dy1 -= 2.0d * ldy1; dx2 -= 2.0d * ldx2; dy2 -= 2.0d * ldy2; r.moveTo((float) x, (float) y); r.lineTo((float) (x+dx1), (float) (y+dy1)); r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.lineTo((float) (x+dx2), (float) (y+dy2)); r.closePath(); } r.pathDone(); if (r.endRendering()) { ptg = rdrCtx.ptg.init(); ptg.getBbox(bbox); // note: do not returnRendererContext(rdrCtx) // as it will be called later by MarlinTileGenerator.dispose() r = null; } } finally { if (r != null) { // dispose renderer and recycle the RendererContext instance: r.dispose(); } } // Return null to cancel AA tile generation (nothing to render) return ptg; }
@Override public final AATileGenerator getAATileGenerator(double x, double y, double dx1, double dy1, double dx2, double dy2, double lw1, double lw2, Region clip, int bbox[]) { // REMIND: Deal with large coordinates! double ldx1, ldy1, ldx2, ldy2; boolean innerpgram = (lw1 > 0.0 && lw2 > 0.0); if (innerpgram) { ldx1 = dx1 * lw1; ldy1 = dy1 * lw1; ldx2 = dx2 * lw2; ldy2 = dy2 * lw2; x -= (ldx1 + ldx2) / 2.0; y -= (ldy1 + ldy2) / 2.0; dx1 += ldx1; dy1 += ldy1; dx2 += ldx2; dy2 += ldy2; if (lw1 > 1.0 && lw2 > 1.0) { // Inner parallelogram was entirely consumed by stroke... innerpgram = false; } } else { ldx1 = ldy1 = ldx2 = ldy2 = 0.0; } MarlinTileGenerator ptg = null; Renderer r = null; final RendererContext rdrCtx = getRendererContext(); try { r = rdrCtx.renderer.init(clip.getLoX(), clip.getLoY(), clip.getWidth(), clip.getHeight(), Renderer.WIND_EVEN_ODD); r.moveTo((float) x, (float) y); r.lineTo((float) (x+dx1), (float) (y+dy1)); r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.lineTo((float) (x+dx2), (float) (y+dy2)); r.closePath(); if (innerpgram) { x += ldx1 + ldx2; y += ldy1 + ldy2; dx1 -= 2.0 * ldx1; dy1 -= 2.0 * ldy1; dx2 -= 2.0 * ldx2; dy2 -= 2.0 * ldy2; r.moveTo((float) x, (float) y); r.lineTo((float) (x+dx1), (float) (y+dy1)); r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.lineTo((float) (x+dx2), (float) (y+dy2)); r.closePath(); } r.pathDone(); if (r.endRendering()) { ptg = rdrCtx.ptg.init(); ptg.getBbox(bbox); // note: do not returnRendererContext(rdrCtx) // as it will be called later by MarlinTileGenerator.dispose() r = null; } } finally { if (r != null) { // dispose renderer: r.dispose(); // recycle the RendererContext instance MarlinRenderingEngine.returnRendererContext(rdrCtx); } } // Return null to cancel AA tile generation (nothing to render) return ptg; }
@Override public final AATileGenerator getAATileGenerator(double x, double y, double dx1, double dy1, double dx2, double dy2, double lw1, double lw2, Region clip, int[] bbox) { // REMIND: Deal with large coordinates! double ldx1, ldy1, ldx2, ldy2; boolean innerpgram = (lw1 > 0.0 && lw2 > 0.0); if (innerpgram) { ldx1 = dx1 * lw1; ldy1 = dy1 * lw1; ldx2 = dx2 * lw2; ldy2 = dy2 * lw2; x -= (ldx1 + ldx2) / 2.0; y -= (ldy1 + ldy2) / 2.0; dx1 += ldx1; dy1 += ldy1; dx2 += ldx2; dy2 += ldy2; if (lw1 > 1.0 && lw2 > 1.0) { // Inner parallelogram was entirely consumed by stroke... innerpgram = false; } } else { ldx1 = ldy1 = ldx2 = ldy2 = 0.0; } MarlinTileGenerator ptg = null; Renderer r = null; final RendererContext rdrCtx = getRendererContext(); try { r = rdrCtx.renderer.init(clip.getLoX(), clip.getLoY(), clip.getWidth(), clip.getHeight(), Renderer.WIND_EVEN_ODD); r.moveTo((float) x, (float) y); r.lineTo((float) (x+dx1), (float) (y+dy1)); r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.lineTo((float) (x+dx2), (float) (y+dy2)); r.closePath(); if (innerpgram) { x += ldx1 + ldx2; y += ldy1 + ldy2; dx1 -= 2.0 * ldx1; dy1 -= 2.0 * ldy1; dx2 -= 2.0 * ldx2; dy2 -= 2.0 * ldy2; r.moveTo((float) x, (float) y); r.lineTo((float) (x+dx1), (float) (y+dy1)); r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); r.lineTo((float) (x+dx2), (float) (y+dy2)); r.closePath(); } r.pathDone(); if (r.endRendering()) { ptg = rdrCtx.ptg.init(); ptg.getBbox(bbox); // note: do not returnRendererContext(rdrCtx) // as it will be called later by MarlinTileGenerator.dispose() r = null; } } finally { if (r != null) { // dispose renderer: r.dispose(); // recycle the RendererContext instance MarlinRenderingEngine.returnRendererContext(rdrCtx); } } // Return null to cancel AA tile generation (nothing to render) return ptg; }
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); } } }
/** * 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 AATileGenerator getAATileGenerator(Shape s, AffineTransform at, Region clip, BasicStroke bs, boolean thin, boolean normalize, int bbox[]) { Renderer r; NormMode norm = (normalize) ? NormMode.ON_WITH_AA : NormMode.OFF; if (bs == null) { PathIterator pi; if (normalize) { pi = new NormalizingPathIterator(s.getPathIterator(at), norm); } else { pi = s.getPathIterator(at); } r = new Renderer(3, 3, clip.getLoX(), clip.getLoY(), clip.getWidth(), clip.getHeight(), pi.getWindingRule()); pathTo(pi, r); } else { r = new Renderer(3, 3, clip.getLoX(), clip.getLoY(), clip.getWidth(), clip.getHeight(), PathIterator.WIND_NON_ZERO); strokeTo(s, at, bs, thin, norm, true, r); } r.endRendering(); PiscesTileGenerator ptg = new PiscesTileGenerator(r, r.MAX_AA_ALPHA); ptg.getBbox(bbox); return ptg; }