All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.pisces.PiscesRenderer Maven / Gradle / Ivy

/*
 * Copyright (c) 2011, 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 com.sun.pisces;

/**
 * PiscesRenderer class is basic public API accessing Pisces library capabilities.
 * 
 * Pisces renderer is intended to draw directly into underlying data buffer of AbstractSurface. 
 * Basic implementation of AbstractSurface is e.g. GraphicsSurface.
 *
 * All coordinates are in 15.16 representation. ie. 13 will be passed as 13<<16.
 * Simple use-case for PiscesRenderer together with GraphicsSurface would be e.g. -
 *
* * *
* GraphicsSurface surface = new GraphicsSurface();
*
* PiscesRenderer pr = new PiscesRenderer(surface);
*
*
*
* Now, when we have instances ready, we can render something from our paint(Graphics g) method *

*
* void paint(Graphics g) {
*
surface.bindTarget(g);
* //we set stroke color
* pr.setColor(0xFF, 0x00, 0xAF);
* // we set required Porter-Duff Compositing Rule
* pr.setComposite(RendererBase.COMPOSITE_SRC_OVER);
*
* //switch antialising on/off as required
* pr.setAntialiasing(true); // on
*
* pr.setTransform(ourTransform6Matrix);
*
* //and now let's draw something finally
* pr.beginRendering(RendererBase.WIND_EVEN_ODD);
* pr.moveTo(50 << 16, 100 << 16); //
* pr.lineTo(30<<16, 1<<16); * pr.endRendering();
*
* surface.releaseTarget();
*
* }
*
*/ public final class PiscesRenderer { public static final int ARC_OPEN = 0; public static final int ARC_CHORD = 1; public static final int ARC_PIE = 2; private long nativePtr = 0L; private AbstractSurface surface; /** * Creates a renderer that will write into a given surface. * * @param surface destination surface */ public PiscesRenderer(AbstractSurface surface) { this.surface = surface; initialize(); } private native void initialize(); /** * Sets the current paint color. * * @param red a value between 0 and 255. * @param green a value between 0 and 255. * @param blue a value between 0 and 255. * @param alpha a value between 0 and 255. */ public native void setColor(int red, int green, int blue, int alpha); /** * Sets the current paint color. An alpha value of 255 is used. Calling setColor also switches * painting mode - i.e. if we have specified gradient, or texture previously, this will be overcome with setColor * call. Also note, that 3-param setColor sets fully opaque RGB color. To draw with semi-transparent color * use 4-param convenience method. * * @param red a value between 0 and 255. * @param green a value between 0 and 255. * @param blue a value between 0 and 255. */ public void setColor(int red, int green, int blue) { setColor(red, green, blue, 255); } /** * Sets current Compositing Rule (Porter-Duff) to be used in following rendering operation. Note that compositeAlpha * is not changed. * @param compositeRule one of RendererBase.COMPOSITE_* constants. */ public native void setCompositeRule(int compositeRule); private native void setLinearGradientImpl(int x0, int y0, int x1, int y1, int[] colors, int cycleMethod, Transform6 gradientTransform); /** * This method sets linear color-gradient data to be used as paint data in following rendering operation. * Imagine, we want to draw simple gradient from blue to red color. Each pixel on line perpendicular to line L = [[x0,y0], [x1, y1]] will have same constant color. * Pixels on perpendicular-line which passes [x0, y0] will be blue. Those on line passing [x1, y1] will be red. Colors on lines in between will be interpolated by fractions. * @param x0 x-coordinate of the starting point of the linear gradient * @param y0 y-coordinate of the starting point of the linear gradient * @param x1 x-coordinate of the end point of the linear gradient * @param y0 y-coordinate of the end point of the linear gradient * @param fractions this array defines normalized distances in which color (rgba[i]) starts to fade into next color (rgba[i+1]). This distance from the point [x0,y0] is given as fraction[i]*l, where l is length of line [[x0,y0], [x1,y1]]. fraction[i+1] says, in what distance fraction[i+1]*l from [x0,y0] should color already have firm value of rgba[i+1]. Values passed in fractions should be from interval <0.0, 1.0>, in 15.16 format. * @param rgba colors which the linear gradient passes through. Generally should be fulfilled this formula rgba.length == fractions.length * @param cycleMethod some value from GradientColorMap.CYCLE_*. @see GradienColorMap * @param gradientTransform transformation applied to gradient paint data. This way we can either transform gradient fill together with filled object or leave it as if transformed gradient-filled object was a window through which we observe gradient area. * @see GradienColorMap */ public void setLinearGradient(int x0, int y0, int x1, int y1, int[] fractions, int[] rgba, int cycleMethod, Transform6 gradientTransform) { final GradientColorMap gradientColorMap = new GradientColorMap(fractions, rgba, cycleMethod); setLinearGradientImpl(x0, y0, x1, y1, gradientColorMap.colors, cycleMethod, gradientTransform == null ? new Transform6(1 << 16, 0, 0, 1 << 16, 0, 0) : gradientTransform); } /** * This method sets linear color-gradient data to be used as paint data in following rendering operation. * Imagine, we want to draw simple gradient from blue to red color. Each pixel on line perpendicular to line L = [[x0,y0], [x1, y1]] will have same constant color. * Pixels on perpendicular-line which passes [x0, y0] will be blue. Those on line passing [x1, y1] will be red. Colors on lines in between will be interpolated by fractions. * @param x0 x-coordinate of the starting point of the linear gradient * @param y0 y-coordinate of the starting point of the linear gradient * @param x1 x-coordinate of the end point of the linear gradient * @param y0 y-coordinate of the end point of the linear gradient * @param gradientColorMap The GradientColorMap calculated with @see calculateLinearGradient. * @param gradientTransform transformation applied to gradient paint data. This way we can either transform gradient fill together with filled object or leave it as if transformed gradient-filled object was a window through which we observe gradient area. * @see GradienColorMap */ public void setLinearGradient(int x0, int y0, int x1, int y1, GradientColorMap gradientColorMap, Transform6 gradientTransform) { setLinearGradientImpl(x0, y0, x1, y1, gradientColorMap.colors, gradientColorMap.cycleMethod, gradientTransform == null ? new Transform6(1 << 16, 0, 0, 1 << 16, 0, 0) : gradientTransform); } /** * Java2D-style linear gradient creation. The color changes proportionally * between point P0 (color0) nad P1 (color1). Cycle method constants are * defined in GradientColorMap (CYCLE_*). This is convenience method only. Same as if setLinearGradient method with 8 parameters was called with * fractions = {0x0000, 0x10000}, rgba = {color0, color1} and identity transformation matrix. * * @param x0 x coordinate of point P0 * @param y0 y coordinate of point P0 * @param color0 color of P0 * @param x1 x coordinate of point P1 * @param y1 y coordinate of point P1 * @param color1 color of P1 * @param cycleMethod type of cycling of the gradient (NONE, REFLECT, REPEAT) * * As Pisces Gradient support was added to support features introduced in SVG, see e.g. http://www.w3.org/TR/SVG11/pservers.html for more information and examples. */ public void setLinearGradient(int x0, int y0, int color0, int x1, int y1, int color1, int cycleMethod) { int[] fractions = {0x0000, 0x10000}; int[] rgba = {color0, color1}; Transform6 ident = new Transform6(1 << 16, 0, 0, 1 << 16, 0, 0); setLinearGradient(x0, y0, x1, y1, fractions, rgba, cycleMethod, ident); } private native void setRadialGradientImpl(int cx, int cy, int fx, int fy, int radius, int[] colors, int cycleMethod, Transform6 gradientTransform); /** * This method sets radial gradient paint data to be used in subsequent rendering. Radial gradient data generated will be used to fill the touched pixels of the path we draw. * * @param cx cx, cy and radius triplet defines the largest circle for the gradient. 100% gradient stop is mapped to perimeter of this circle. * @param cy * @param fx fx,fy defines focal point of the gradient. ie. 0% gradient stop is mapped to fx,fy point. If cx == fx and cy == fy, then gradient consists of homocentric circles. If these relations are not met, gradient field is deformed and eccentric ovals can be observed. * @param fy * @param radius @see cx * @param fractions @see setLinearGradient * @param rgba @see setLinearGradient * @param cycleMethod @see setLinearGradient * @param gradientTransform @see setLinearGradient * * As Pisces Gradient support was added to support features introduced in SVG, see e.g. http://www.w3.org/TR/SVG11/pservers.html for more information and examples. */ public void setRadialGradient(int cx, int cy, int fx, int fy, int radius, int[] fractions, int[] rgba, int cycleMethod, Transform6 gradientTransform) { final GradientColorMap gradientColorMap = new GradientColorMap(fractions, rgba, cycleMethod); setRadialGradientImpl(cx, cy, fx, fy, radius, gradientColorMap.colors, cycleMethod, gradientTransform == null ? new Transform6(1 << 16, 0, 0, 1 << 16, 0, 0) : gradientTransform); } /** * This method sets radial gradient paint data to be used in subsequent rendering. Radial gradient data generated will be used to fill the touched pixels of the path we draw. * * @param cx cx, cy and radius triplet defines the largest circle for the gradient. 100% gradient stop is mapped to perimeter of this circle. * @param cy * @param fx fx,fy defines focal point of the gradient. ie. 0% gradient stop is mapped to fx,fy point. If cx == fx and cy == fy, then gradient consists of homocentric circles. If these relations are not met, gradient field is deformed and eccentric ovals can be observed. * @param fy * @param radius @see cx * @param gradientColorMap @see setLinearGradient * @param gradientTransform @see setLinearGradient * * As Pisces Gradient support was added to support features introduced in SVG, see e.g. http://www.w3.org/TR/SVG11/pservers.html for more information and examples. */ public void setRadialGradient(int cx, int cy, int fx, int fy, int radius, GradientColorMap gradientColorMap, Transform6 gradientTransform) { setRadialGradientImpl(cx, cy, fx, fy, radius, gradientColorMap.colors, gradientColorMap.cycleMethod, gradientTransform == null ? new Transform6(1 << 16, 0, 0, 1 << 16, 0, 0) : gradientTransform); } public void setTexture(int imageType, int data[], int width, int height, Transform6 textureTransform, boolean repeat, boolean hasAlpha) { if (width < 0) { throw new IllegalArgumentException("WIDTH must be positive"); } if (height < 0) { throw new IllegalArgumentException("HEIGHT must be positive"); } final int nbits = 32-Integer.numberOfLeadingZeros(width) + 32-Integer.numberOfLeadingZeros(height); if (nbits > 31) { throw new IllegalArgumentException("WIDTH * HEIGHT is too large"); } if ((width * height) > data.length) { throw new IllegalArgumentException("WIDTH * HEIGHT exceeds length of data"); } this.setTextureImpl(imageType, data, width, height, textureTransform, repeat, hasAlpha); } private native void setTextureImpl(int imageType, int data[], int width, int height, Transform6 textureTransform, boolean repeat, boolean hasAlpha); /** * Sets a clip rectangle for all primitives. Each primitive will be * clipped to the intersection of this rectangle and the destination * image bounds. */ public void setClip(int minX, int minY, int width, int height) { final int x1 = Math.max(minX, 0); final int y1 = Math.max(minY, 0); final int x2 = Math.min(minX + width, surface.getWidth()); final int y2 = Math.min(minY + height, surface.getHeight()); this.setClipImpl(x1, y1, x2 - x1, y2 - y1); } private native void setClipImpl(int minX, int minY, int width, int height); /** * Resets the clip rectangle. Each primitive will be clipped only * to the destination image bounds. */ public void resetClip() { this.setClipImpl(0, 0, surface.getWidth(), surface.getHeight()); } /** * Clears rectangle (x, y, x + w, y + h). Clear sets all pixels to transparent black (0x00000000 ARGB). */ public native void clearRect(int x, int y, int w, int h); public native void fillRect(int x, int y, int w, int h); public void emitAndClearAlphaRow(byte[] alphaMap, int[] alphaDeltas, int pix_y, int pix_x_from, int pix_x_to, int rowNum) { if ((pix_x_to - pix_x_from) > alphaDeltas.length) { throw new IllegalArgumentException("rendering range exceeds length of data"); } this.emitAndClearAlphaRowImpl(alphaMap, alphaDeltas, pix_y, pix_x_from, pix_x_to, rowNum); } private native void emitAndClearAlphaRowImpl(byte[] alphaMap, int[] alphaDeltas, int pix_y, int pix_x_from, int pix_x_to, int rowNum); public void fillAlphaMask(byte[] mask, int x, int y, int width, int height, int offset, int stride) { if (mask == null) { throw new NullPointerException("Mask is NULL"); } this.inputImageCheck(width, height, offset, stride, mask.length); this.fillAlphaMaskImpl(mask, x, y, width, height, offset, stride); } private native void fillAlphaMaskImpl(byte[] mask, int x, int y, int width, int height, int offset, int stride); public native void setLCDGammaCorrection(float gamma); public void fillLCDAlphaMask(byte[] mask, int x, int y, int subPosX, int width, int height, int offset, int stride) { if (mask == null) { throw new NullPointerException("Mask is NULL"); } this.inputImageCheck(width, height, offset, stride, mask.length); if (subPosX < 0 || subPosX > 2) { throw new IllegalArgumentException("subPosX must be 0,1 or 2, curVal: " + subPosX); } this.fillLCDAlphaMaskImpl(mask, x, y, subPosX, width, height, offset, stride); } private native void fillLCDAlphaMaskImpl(byte[] mask, int x, int y, int subPosX, int width, int height, int offset, int stride); public void drawImage(int imageType, int imageMode, int data[], int width, int height, int offset, int stride, Transform6 textureTransform, boolean repeat, int bboxX, int bboxY, int bboxW, int bboxH, int interpolateMinX, int interpolateMinY, int interpolateMaxX, int interpolateMaxY, boolean hasAlpha) { this.inputImageCheck(width, height, offset, stride, data.length); this.drawImageImpl(imageType, imageMode, data, width, height, offset, stride, textureTransform, repeat, bboxX, bboxY, bboxW, bboxH, interpolateMinX, interpolateMinY, interpolateMaxX, interpolateMaxY, hasAlpha); } private native void drawImageImpl(int imageType, int imageMode, int data[], int width, int height, int offset, int stride, Transform6 textureTransform, boolean repeat, int bboxX, int bboxY, int bboxW, int bboxH, int interpolateMinX, int interpolateMinY, int interpolateMaxX, int interpolateMaxY, boolean hasAlpha); private void inputImageCheck(int width, int height, int offset, int stride, int data_length) { if (width < 0) { throw new IllegalArgumentException("WIDTH must be positive"); } if (height < 0) { throw new IllegalArgumentException("HEIGHT must be positive"); } if (offset < 0) { throw new IllegalArgumentException("OFFSET must be positive"); } if (stride < 0) { throw new IllegalArgumentException("STRIDE must be positive"); } if (stride < width) { throw new IllegalArgumentException("STRIDE must be >= WIDTH"); } final int nbits = 32-Integer.numberOfLeadingZeros(stride) + 32-Integer.numberOfLeadingZeros(height); if (nbits > 31) { throw new IllegalArgumentException("STRIDE * HEIGHT is too large"); } if ((offset + stride*(height-1) + width) > data_length) { throw new IllegalArgumentException("STRIDE * HEIGHT exceeds length of data"); } } protected void finalize() { this.nativeFinalize(); } /** * Native finalizer. Releases native memory used by PiscesRenderer at lifetime. */ private native void nativeFinalize(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy