FileDocCategorySizeDatePackage
PiscesRenderer.javaAPI DocphoneME MR2 API (J2ME)13932Wed May 02 18:00:36 BST 2007com.sun.pisces

PiscesRenderer.java

/*
 * 
 * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved. 
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER 
 *  
 * This program 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. 
 *  
 * This program 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 at /legal/license.txt). 
 *  
 * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa 
 * Clara, CA 95054 or visit www.sun.com if you need additional 
 * information or have any questions.
 */
 
 
package com.sun.pisces;

public final class PiscesRenderer extends PathSink 
        implements NativeFinalization {
    static {
        PiscesLibrary.load();
    }

    private static boolean messageShown = false;

    public static final int ARC_OPEN = 0;
    public static final int ARC_CHORD = 1;
    public static final int ARC_PIE = 2;
    
    long nativePtr = 0L;
    final AbstractSurface surface;

    private final NativeFinalizer finalizer;
        
    static {
        String strValue;
        int strokeXBias = 0; // default x bias
        int strokeYBias = 0; // default y bias

        strValue = Configuration.getProperty("pisces.stroke.xbias");
        if (strValue != null) {
            try {
                strokeXBias = Integer.parseInt(strValue);
            } catch (NumberFormatException e) {
            }
        }
        
        strValue = Configuration.getProperty("pisces.stroke.ybias");
        if (strValue != null) {
            try {
                strokeYBias = Integer.parseInt(strValue);
            } catch (NumberFormatException e) {
            }
        }

        staticInitialize(strokeXBias, strokeYBias);
    }
    
    private void notImplemented() {
        new RuntimeException().printStackTrace();
        System.out.println("not implemented");

//         throw new RuntimeException("PiscesRendererNativeImpl: " +
//                 "Not implemented!");
    }
    
    /**
     * Creates a renderer that will write into a given pixel array.
     *
     * @param data the destination surface
     * where pixel data should be written.
     * @param width the width of the pixel array.
     * @param height the height of the pixel array.
     * @param offset the starting offset of the pixel array.
     * @param scanlineStride the scanline stride of the pixel array, in array
     * entries.
     * @param pixelStride the pixel stride of the pixel array, in array
     * entries.
     * @param type the pixel format, one of the
     * <code>RendererBase.TYPE_*</code> constants.
     */
    public PiscesRenderer(Object data, int width, int height,
                          int offset, int scanlineStride, int pixelStride,
                          int type) {
        this((AbstractSurface)data);
    }

    public PiscesRenderer(AbstractSurface surface) {
        if (!messageShown) {
            System.out.println("Using Pisces Renderer (native version)");
        }

        this.finalizer = NativeFinalizer.createInstance(this);
        this.surface = surface;
        initialize();
        messageShown = true;
    }

    private static native void staticInitialize(int strokeXBias, 
            int strokeYBias);

    private native void initialize();
    
    public native void setAntialiasing(boolean antialiasingOn);

    public native boolean getAntialiasing();

    /**
     * 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.
     *
     * @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);
    }
    
    public native void setCompositeRule(int compositeRule);

    public native void setComposite(int compositeRule, float alpha);

    int[] gcm_fractions = null;
    int[] gcm_rgba = null;
    int gcm_cycleMethod = -1;
    GradientColorMap gradientColorMap = null;
    
    private boolean arraysDiffer(int[] a, int[] b) {
        if (a == null) {
            return true;
        }
        int len = b.length;
        if (a.length != len) {
            return true;
        }
        for (int i = 0; i < len; i++) {
            if (a[i] != b[i]) {
                return true;
            }
        }
        
        return false;
    }
    
    private int[] cloneArray(int[] src) {
        int len = src.length;
        int[] dst = new int[len];
        System.arraycopy(src, 0, dst, 0, len);
        return dst;
    }
    
    private void setGradientColorMap(int[] fractions, int[] rgba,
                                     int cycleMethod) {
        if (fractions.length != rgba.length) {
            throw new IllegalArgumentException("fractions.length != rgba.length!");
        }
        
        if (gradientColorMap == null ||
            gcm_cycleMethod != cycleMethod ||
            arraysDiffer(gcm_fractions, fractions) ||
            arraysDiffer(gcm_rgba, rgba)) {
            this.gradientColorMap =
                new GradientColorMap(fractions, rgba, cycleMethod);
            this.gcm_cycleMethod = cycleMethod;
            this.gcm_fractions = cloneArray(fractions);
            this.gcm_rgba = cloneArray(rgba);
        }
    }
    
    private native void setLinearGradientImpl(int x0, int y0, int x1, int y1,
                                              int[] colors,
                                              int cycleMethod,
                                              Transform6 gradientTransform);

    public void setLinearGradient(int x0, int y0, int x1, int y1,
                                  int[] fractions, int[] rgba,
                                  int cycleMethod,
                                  Transform6 gradientTransform) {
        setGradientColorMap(fractions, rgba, cycleMethod);
        setLinearGradientImpl(x0, y0, x1, y1,
                              gradientColorMap.colors, cycleMethod,
                              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_*).          
     *
     * @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)
     *          
     */
    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);

    public void setRadialGradient(int cx, int cy, int fx, int fy,
                                  int radius,
                                  int[] fractions, int[] rgba,
                                  int cycleMethod,
                                  Transform6 gradientTransform) {
        setGradientColorMap(fractions, rgba, cycleMethod);
        setRadialGradientImpl(cx, cy, fx, fy, radius,
                              gradientColorMap.colors, cycleMethod,
                              gradientTransform);
    }

    public void setTextureOpacity(float opacity) {
	notImplemented();
    }

    public void setTexture(int imageType,
                           Object imageData, 
                           int width, int height,
                           int offset, int stride,
                           Transform6 textureTransform,
                           boolean repeat) {
        if (imageData instanceof int[]) {
            setTextureImpl(imageType, (int[])imageData, width, height, offset, 
                    stride, textureTransform, repeat);
        }
    }

     private native void setTextureImpl(int imageType, int[] imageData,
            int width, int height, int offset, int stride,
            Transform6 textureTransform, boolean repeat);
    
    public PathSink getStroker() {
        notImplemented();
        return null;
    }

    public PathSink getFiller() {
        notImplemented();
        return null;
    }

    public PathSink getTextFiller() {
        notImplemented();
        return null;
    }

    /**
     * Sets the current stroke parameters.
     *
     * @param lineWidth the sroke width, in S15.16 format.
     * @param capStyle the line cap style, one of
     * <code>Stroker.CAP_*</code>.
     * @param joinStyle the line cap style, one of
     * <code>Stroker.JOIN_*</code>.
     * @param miterLimit the stroke miter limit, in S15.16 format.
     * @param dashArray an <code>int</code> array containing the dash
     * segment lengths in S15.16 format, or <code>null</code>.
     * @param dashPhase the starting dash offset, in S15.16 format.
     */
    public native void setStroke(int lineWidth, int capStyle, int joinStyle,
            int miterLimit, int[] dashArray, int dashPhase);

    /**
     * Sets the current transform from user to window coordinates.
     *
     * @param transform an <code>Transform6</code> object.
     */
    public native void setTransform(Transform6 transform);
    
    public Transform6 getTransform() {
        Transform6 transform = new Transform6();
        getTransformImpl(transform);
        return transform;
    }
    
    private native void getTransformImpl(Transform6 transform);

    /**
     * Sets a clip rectangle for all primitives.  Each primitive will be
     * clipped to the intersection of this rectangle and the destination
     * image bounds.
     */
    public native void setClip(int minX, int minY, int width, int height);

    /**
     * Resets the clip rectangle.  Each primitive will be clipped only
     * to the destination image bounds.
     */
    public native void resetClip();

    public native void beginRendering(int windingRule);

    /**
     * Begins the rendering of path data.  The supplied clipping
     * bounds are intersected against the current clip rectangle and
     * the destination image bounds; only pixels within the resulting
     * rectangle may be written to.
     */
    public native void beginRendering(int minX, int minY, 
            int width, int height, int windingRule);

    /**
     * Completes the rendering of path data.  Destination pixels will
     * be written at this time.
     */
    public native void endRendering();

    /**
     * Returns a bounding box containing all pixels drawn during the
     * rendering of the most recent primitive
     * (beginRendering/endRendering pair).  The bounding box is
     * returned in the form (x, y, width, height).
     */
    public native void getBoundingBox(int[] bbox);
    
    public native void setStroke();
    
    public native void setFill();

    public void setTextFill() {
        notImplemented();
    }

    public native void moveTo(int x0, int y0);

    public native void lineTo(int x1, int y1);

    public native void lineJoin();

    public native void quadTo(int x1, int y1, int x2, int y2);

    public native void cubicTo(int x1, int y1, int x2, int y2, int x3, int y3);

    public native void close();

    public native void end();

    public native void drawLine(int x0, int y0, int x1, int y1);

    /**
     * 
     * @param x the X coordinate in S15.16 format.
     * @param y the Y coordinate in S15.16 format.
     * @param w the width in S15.16 format.
     * @param h the height in S15.16 format.
     */
    public native void fillRect(int x, int y, int w, int h);

    public native void drawRect(int x, int y, int w, int h);

    public native void drawOval(int x, int y, int w, int h);

    public native void fillOval(int x, int y, int w, int h);

    public native void fillRoundRect(int x, int y, int w, int h, 
            int aw, int ah);

    public native void drawRoundRect(int x, int y, int w, int h, 
            int aw, int ah);

    public native void drawArc(int x, int y, int width, int height,
            int startAngle, int arcAngle, int arcType);

    public native void fillArc(int x, int y, int width, int height,
            int startAngle, int arcAngle, int arcType);

    public void getImageData() {
        notImplemented();
    }
    
    public native void clearRect(int x, int y, int w, int h);

    public native void setPathData(float[] data, byte[] commands, 
            int nCommands);

    public native void nativeFinalize();
}