Index: modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/GL.java =================================================================== --- modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/GL.java (revision 507070) +++ modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/GL.java (working copy) @@ -303,5 +303,21 @@ public final native void glStencilOp(int fail, int zfail, int zpass); + + + public final native int glGenLists(int range); + + public final native byte glIsList(int list); + + public final native void glDeleteLists(int list, int range); + + public final native void glNewList(int list, int mode); + + public final native void glCallList(int list); + + public final native void glEndList(); + } + + Index: modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLGraphics2D.java =================================================================== --- modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLGraphics2D.java (revision 507070) +++ modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLGraphics2D.java (working copy) @@ -35,6 +35,7 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.geom.Point2D; +import java.awt.font.GlyphVector; import java.util.Arrays; import java.math.BigInteger; @@ -195,6 +196,8 @@ origPoint = new Point(tx, ty); blitter = OGLBlitter.getInstance(); + + jtr = new OGLTextRenderer(); } public OGLGraphics2D(NativeWindow nwin, int tx, int ty, int width, int height) { @@ -430,10 +433,38 @@ } @Override - public void drawString(String str, int x, int y) { - // XXX - todo + public void drawString(String str, float x, float y) { + makeCurrent(); + + if (paint instanceof Color) { + AffineTransform at = (AffineTransform) glTransform.clone(); + jtr.drawString(this, str, x, y); + setTransform(at); + } else { + this.fill(font.createGlyphVector(this.getFontRenderContext(), str).getOutline(x, y)); + } + + gl.glFlush(); + getSurface().updateScene(); } + @Override + public void drawGlyphVector(GlyphVector gv, float x, float y) { + makeCurrent(); + + if (paint instanceof Color) { + AffineTransform at = (AffineTransform) glTransform.clone(); + jtr.drawGlyphVector(this, gv, x, y); + setTransform(at); + } else { + this.fill(gv.getOutline(x, y)); + } + + gl.glFlush(); + getSurface().updateScene(); + } + + @Override protected void setTransformedClip(MultiRectArea clip) { super.setTransformedClip(clip); Index: modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLTextRenderer.java =================================================================== --- modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLTextRenderer.java (revision 0) +++ modules/awt/src/main/java/common/org/apache/harmony/awt/gl/opengl/OGLTextRenderer.java (revision 0) @@ -0,0 +1,436 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.awt.gl.opengl; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.font.GlyphMetrics; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.lang.ref.SoftReference; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Vector; + +import org.apache.harmony.awt.gl.Surface; +import org.apache.harmony.awt.gl.TextRenderer; +import org.apache.harmony.awt.gl.font.CommonGlyphVector; +import org.apache.harmony.awt.gl.font.FontPeerImpl; +import org.apache.harmony.awt.gl.font.Glyph; + +import org.apache.harmony.misc.HashCode; + +import org.apache.harmony.awt.internal.nls.Messages; + +public class OGLTextRenderer extends TextRenderer { + + private static final TextureCache tx = TextureCache.getInstance(); + private static final GL gl = GL.getInstance(); + + private static final HashSet ESCAPE = new HashSet(); + static { + ESCAPE.add(new Character('\n')); + ESCAPE.add(new Character('\r')); + ESCAPE.add(new Character('\t')); + } + + private static final Hashtable intHash2glyphHash = new SoftHashtable(); + + private static final Vector toDel = new Vector(); + + private static final Color INVISIBLE_COLOR = new Color(0,0,0,(float)0); + + public static final BufferedImage getBufImg(byte[] pixels, int width, int height, Color color) { + if (pixels == null) { + return new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY); + } + + WritableRaster wr = Raster.createPackedRaster( + new DataBufferByte(pixels, pixels.length), + (pixels.length / height) << 3, + height, + 1, + null + ); + + int[] masColors = new int[]{ (int)0x000000, color.getRGB()}; + + IndexColorModel colorModel = new IndexColorModel(1, 2, masColors, 0,true,0,DataBuffer.TYPE_BYTE); + + BufferedImage bim = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED, colorModel); + + bim.setData( wr.createWritableChild(0, 0, width, height, 0, 0, null)); + + return bim; + } + + /** + * Draws string on specified Graphics at desired position. + * + * @param g specified Graphics2D object + * @param str String object to draw + * @param x start X position to draw + * @param y start Y position to draw + */ + public void drawString(Graphics2D g, String str, float x, float y) { + char[] input = str.toCharArray(); + Character ch; + Glyph glyph; + DLInfo info; + GlyphMetrics glMetrics; + Color col = g.getColor(); + Font font = g.getFont(); + int lenght = str.length(); + FontPeerImpl peer = ((FontPeerImpl)font.getPeer()); + AffineTransform fontAT = (AffineTransform)font.getTransform().clone(); + Point.Float pos = new Point.Float(); + Paint paint = g.getPaint(); + boolean isAntialias = g.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING) == RenderingHints.VALUE_TEXT_ANTIALIAS_ON; + + try { + fontAT.inverseTransform(new Point.Double(x + fontAT.getTranslateX(), y + fontAT.getTranslateY()), pos); + } catch (NoninvertibleTransformException e) { +// TODO determinant equals 0 => point or line + g.fill(font.createGlyphVector(g.getFontRenderContext(), str).getOutline(x, y)); + return; + } + + fontAT.translate(pos.x,pos.y); + g.transform(fontAT); + + HashCode hash = new HashCode(); + hash.append(peer); + hash.append(getFactor(g.getTransform())); + hash.append(paint); + hash.append(isAntialias); + Integer intHash = new Integer(hash.hashCode()); + + GlyphHashtable glyphHash = + intHash2glyphHash.containsKey(intHash) ? + (GlyphHashtable) intHash2glyphHash.get(intHash) : null; + if ( glyphHash == null) { + glyphHash = new GlyphHashtable(); + intHash2glyphHash. put(intHash, glyphHash); + } + + activateVars(); + + for (int i = 0; i - lenght < 0; i ++) { + ch = new Character(input[i]); + if (ESCAPE.contains(ch)) continue; + glyph = peer.getGlyph(input[i]); + + if (ch == ' ') { + glMetrics = glyph.getGlyphPointMetrics(); + gl.glTranslated( + glMetrics.getAdvanceX(), + glMetrics.getAdvanceY(), + 0 + ); + continue; + } + + info = glyphHash.containsKey(ch) ? (DLInfo)glyphHash.get(ch) : null; + + if (info == null || !info.isValid()) { + createColorGlyphDL(g, glyph, glyphHash, font, ch, col, isAntialias); + } else { + gl.glCallList(info.getDL()); + } + + glMetrics = glyph.getGlyphPointMetrics(); + gl.glTranslated( + glMetrics.getAdvanceX(), + glMetrics.getAdvanceY(), + 0 + ); + + } + deactivateVars(); + cleanLists(); + + } + + /** + * Draws GlyphVector on specified Graphics at desired position. + * + * @param g specified Graphics2D object + * @param glyphVector GlyphVector object to draw + * @param x start X position to draw + * @param y start Y position to draw + */ + public void drawGlyphVector(Graphics2D g, GlyphVector gv, float x, float y) { + Character ch; + DLInfo info; + Color col = g.getColor(); + Glyph[] input = ((CommonGlyphVector)gv).vector; + Font font = gv.getFont(); + int lenght = gv.getNumGlyphs(); + FontPeerImpl peer = ((FontPeerImpl)font.getPeer()); + AffineTransform fontAT = (AffineTransform)font.getTransform().clone(); + Point.Float pos = new Point.Float(); + boolean isAntialias = g.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING) == RenderingHints.VALUE_TEXT_ANTIALIAS_ON; + + try { + fontAT.inverseTransform(new Point.Double(x + fontAT.getTranslateX(), y + fontAT.getTranslateY()), pos); + } catch (NoninvertibleTransformException e) { + //TODO determinant equals 0 => point or line + g.fill(gv.getOutline(x, y)); + return; + } + + fontAT.translate(pos.getX(), pos.getY()); + g.transform(fontAT); + + HashCode hash = new HashCode(); + hash.append(peer); + hash.append(getFactor(g.getTransform())); + hash.append(g.getPaint()); + hash.append(isAntialias); + Integer intHash = new Integer(hash.hashCode()); + + GlyphHashtable glyphHash = + intHash2glyphHash.containsKey(intHash) ? + (GlyphHashtable) intHash2glyphHash.get(intHash) : null; + if ( glyphHash == null) { + glyphHash = new GlyphHashtable(); + intHash2glyphHash. put(intHash, glyphHash); + } + + fontAT = (AffineTransform) font.getTransform().clone(); + activateVars(); + for (int i = 0; i - lenght < 0; i ++) { + ch = new Character(input[i].getChar()); + + if (ch == ' ') continue; + + info = glyphHash.containsKey(ch) ? (DLInfo)glyphHash.get(ch) : null; + try { + fontAT.inverseTransform(gv.getGlyphPosition(i), pos); + } catch (NoninvertibleTransformException e) { + } + + gl.glTranslated(pos.x, pos.y, 0); + if (info == null || !info.isValid()) { + createColorGlyphDL(g, input[i], glyphHash, font, ch, col, isAntialias); + } else { + gl.glCallList(info.getDL()); + } + gl.glTranslated(-pos.x, -pos.y, 0); + } + deactivateVars(); + cleanLists(); + } + + /** + * @param ogl + * @param glyph + * @param glyphHash + * @param font + */ + private void createColorGlyphDL(Graphics2D g, Glyph glyph, GlyphHashtable glyphHash, Font font, Character ch, Color col, boolean isAntialias) { + int base = gl.glGenLists(1); + if (base == 0) { + //awt.296 can't allocate memory on video card to create new display list + throw new NullPointerException(Messages.getString("awt.296")); + } + + double texSize = getFactor(g.getTransform()); + + Glyph newGlyph = ((FontPeerImpl)(font.deriveFont( + (float)(font.getSize2D() * texSize))).getPeer()) + .getGlyph(ch.charValue()); + + byte[] pixels = newGlyph.getBitmap(); + + BufferedImage bim = getBufImg( + pixels, + newGlyph.getPointWidth(), + newGlyph.getPointHeight(), + col + ); + + Rectangle.Double rect = new Rectangle.Double( + Math.round(glyph.getGlyphPointMetrics().getLSB()), + Math.round(-newGlyph.bmp_top / texSize), + glyph.getPointWidth(), + glyph.getPointHeight() + ); + + Surface sur = Surface.getImageSurface(bim); + + OGLBlitter.OGLTextureParams tp = OGLBlitter.getInstance().blitImg2OGLTexCached( + sur, + bim.getWidth(), + bim.getHeight(), + true + ); + + gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_WRAP_S, GLDefs.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_WRAP_T, GLDefs.GL_CLAMP_TO_EDGE); + + if (isAntialias) { + gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_MAG_FILTER, GLDefs.GL_LINEAR); + gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_MIN_FILTER, GLDefs.GL_LINEAR); + } else { + gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_MAG_FILTER, GLDefs.GL_NEAREST); + gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_MIN_FILTER, GLDefs.GL_NEAREST); + } + + double widthFactor = rect.getWidth() / tp.width * tp.p2w; + double heightFactor = rect.getHeight() / tp.height * tp.p2h; + + gl.glNewList(base, GLDefs.GL_COMPILE_AND_EXECUTE); + + g.setColor(INVISIBLE_COLOR); + + gl.glBindTexture(GLDefs.GL_TEXTURE_2D, tp.textureName); + + gl.glBegin(GLDefs.GL_QUADS); + + gl.glTexCoord2d(0.0, 0.0); + gl.glVertex2d(rect.getX(), rect.getY()); + gl.glTexCoord2d(0.0, rect.getHeight()/heightFactor); + gl.glVertex2d(rect.getX(), rect.getY() + rect.getHeight()); + gl.glTexCoord2d(rect.getWidth()/widthFactor,rect.getHeight()/heightFactor); + gl.glVertex2d(rect.getWidth() + rect.getX(), rect.getY() + rect.getHeight()); + gl.glTexCoord2d(rect.getWidth()/widthFactor,0.0); + gl.glVertex2d(rect.getWidth() + rect.getX(), rect.getY()); + + gl.glEnd(); + + g.setColor(col); + + gl.glEndList(); + + glyphHash.put(ch, new DLInfo(base, sur)); + +// System.out.println("create new dl - " + base); + } + + private double getFactor(AffineTransform at) { + return Math.max(at.getScaleX(), at.getScaleY()); + } + + private void cleanLists() { + synchronized(toDel) { + if (!toDel.isEmpty()) { + for (Iterator iter = toDel.iterator(); iter.hasNext();) { + int element = ((Integer)iter.next()).intValue(); + if (gl.glIsList(element) == GLDefs.GL_TRUE) { + + gl.glDeleteLists(element, 1); +// System.err.println("delete dl - " + element); + } + } + toDel.clear(); + } + } + } + + private void activateVars() { +// gl.glPixelStorei(GLDefs.GL_UNPACK_ALIGNMENT, 1); + gl.glTexEnvf(GLDefs.GL_TEXTURE_ENV, GLDefs.GL_TEXTURE_ENV_MODE, GLDefs.GL_REPLACE); + + gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_WRAP_S, GLDefs.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(GLDefs.GL_TEXTURE_2D, GLDefs.GL_TEXTURE_WRAP_T, GLDefs.GL_CLAMP_TO_EDGE); + + gl.glTexGeni(GLDefs.GL_S, GLDefs.GL_TEXTURE_GEN_MODE, GLDefs.GL_OBJECT_LINEAR); + gl.glTexGeni(GLDefs.GL_T, GLDefs.GL_TEXTURE_GEN_MODE, GLDefs.GL_OBJECT_LINEAR); + + gl.glDisable(GLDefs.GL_TEXTURE_GEN_S); + gl.glDisable(GLDefs.GL_TEXTURE_GEN_T); + + gl.glEnable(GLDefs.GL_TEXTURE_2D); + } + + private void deactivateVars() { + gl.glDisable(GLDefs.GL_TEXTURE_2D); + } + + private static final class SoftHashtable extends Hashtable { + + public Object put(Object key,Object obj) { + SoftReference ref = (SoftReference)super.put(key,new SoftReference(obj)); + return ref == null ? null : ref.get(); + } + + public Object get(Object key) { + SoftReference ref = (SoftReference)super.get(key); + return ref == null ? null : ref.get(); + } + + public Object remove(Object key) { + SoftReference ref = (SoftReference)super.remove(key); + return ref == null ? null : ref.get(); + } + } + + private static final class GlyphHashtable extends Hashtable { + public void finalize() throws Throwable { + super.finalize(); + synchronized(toDel) { + for (Iterator i = this.values().iterator(); i.hasNext();) { + toDel.add(new Integer(((DLInfo) i.next()).getDL())); + } + } + } + } + + private static final class DLInfo { + private int dl; + private Surface srf; + public DLInfo(int dl, Surface srf) { + this.dl = dl; + this.srf = srf; + } + + public int getDL() { + return dl; + } + + public Surface getSrf() { + return srf; + } + + public boolean isValid() { + if (tx.findTexture(srf) == null) { + synchronized (toDel) { + toDel.add(new Integer(dl)); + } + return false; + } + + return gl.glIsList(dl) == GLDefs.GL_TRUE; + } + } + +} Index: modules/awt/src/main/java/common/org/apache/harmony/awt/internal/nls/messages.properties =================================================================== --- modules/awt/src/main/java/common/org/apache/harmony/awt/internal/nls/messages.properties (revision 507070) +++ modules/awt/src/main/java/common/org/apache/harmony/awt/internal/nls/messages.properties (working copy) @@ -484,6 +484,7 @@ awt.292=Source and destination images do not have the same height! awt.294=pixel is null awt.295=data is null +awt.296=can't allocate memory on video card to create new display list awt.err.00=file dialog {0} error! awt.err.01=error: {0} Index: modules/awt/src/main/native/oglwrapper/unix/exports.txt =================================================================== --- modules/awt/src/main/native/oglwrapper/unix/exports.txt (revision 507070) +++ modules/awt/src/main/native/oglwrapper/unix/exports.txt (working copy) @@ -60,3 +60,9 @@ Java_org_apache_harmony_awt_gl_opengl_GL_glDrawBuffer Java_org_apache_harmony_awt_gl_opengl_GL_glReadBuffer Java_org_apache_harmony_awt_gl_opengl_GL_glStencilOp +Java_org_apache_harmony_awt_gl_opengl_GL_glIsList; +Java_org_apache_harmony_awt_gl_opengl_GL_glNewList; +Java_org_apache_harmony_awt_gl_opengl_GL_glCallList; +Java_org_apache_harmony_awt_gl_opengl_GL_glEndList; +Java_org_apache_harmony_awt_gl_opengl_GL_glGenLists; +Java_org_apache_harmony_awt_gl_opengl_GL_glDeleteLists; \ No newline at end of file Index: modules/awt/src/main/native/oglwrapper/shared/org_apache_harmony_awt_gl_opengl_GL.cpp =================================================================== --- modules/awt/src/main/native/oglwrapper/shared/org_apache_harmony_awt_gl_opengl_GL.cpp (revision 507070) +++ modules/awt/src/main/native/oglwrapper/shared/org_apache_harmony_awt_gl_opengl_GL.cpp (working copy) @@ -579,3 +579,58 @@ } (* p_nbridge_glStencilOp)((int) fail, (int) zfail, (int) zpass); } + +unsigned int (__stdcall* p_nbridge_glGenLists) (int) = NULL; + +JNIEXPORT jint JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glGenLists( JNIEnv *env, jobject self, jint range) { + if (p_nbridge_glGenLists == NULL) { + p_nbridge_glGenLists = (unsigned int (__stdcall*) (int)) FindFunction(libGL, "glGenLists"); + } + return (jint) (* p_nbridge_glGenLists)((int) range); +} + +unsigned char (__stdcall* p_nbridge_glIsList) (int) = NULL; + +JNIEXPORT jbyte JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glIsList( JNIEnv *env, jobject self, jint list) { + if (p_nbridge_glIsList == NULL) { + p_nbridge_glIsList = (unsigned char (__stdcall*) (int)) FindFunction(libGL, "glIsList"); + } + return (jbyte) (* p_nbridge_glIsList)((int) list); +} + +void (* p_nbridge_glDeleteLists) (int, int) = NULL; + +JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glDeleteLists( JNIEnv *env, jobject self, jint list, jint range) { + if (p_nbridge_glDeleteLists == NULL) { + p_nbridge_glDeleteLists = (void (*) (int, int)) FindFunction(libGL, "glDeleteLists"); + } + (* p_nbridge_glDeleteLists)((int) list, (int) range); +} + +void (__stdcall* p_nbridge_glNewList) (int, int) = NULL; + +JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glNewList( JNIEnv *env, jobject self, jint list, jint mode) { + if (p_nbridge_glNewList == NULL) { + p_nbridge_glNewList = (void (__stdcall*) (int, int)) FindFunction(libGL, "glNewList"); + } + (* p_nbridge_glNewList)((int) list, (int) mode); +} + +void (* p_nbridge_glCallList) (int) = NULL; + +JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glCallList( JNIEnv *env, jobject self, jint list) { + if (p_nbridge_glCallList == NULL) { + p_nbridge_glCallList = (void (*) (int)) FindFunction(libGL, "glCallList"); + } + (* p_nbridge_glCallList)((int) list); +} + +void (__stdcall* p_nbridge_glEndList) (void) = NULL; + +JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glEndList( JNIEnv *env, jobject self) { + if (p_nbridge_glEndList == NULL) { + p_nbridge_glEndList = (void (__stdcall*) (void)) FindFunction(libGL, "glEndList"); + } + (* p_nbridge_glEndList)(); +} + Index: modules/awt/src/main/native/oglwrapper/shared/org_apache_harmony_awt_gl_opengl_GL.h =================================================================== --- modules/awt/src/main/native/oglwrapper/shared/org_apache_harmony_awt_gl_opengl_GL.h (revision 507070) +++ modules/awt/src/main/native/oglwrapper/shared/org_apache_harmony_awt_gl_opengl_GL.h (working copy) @@ -154,6 +154,14 @@ JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glReadBuffer(JNIEnv *, jobject, jint); JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glStencilOp(JNIEnv *, jobject, jint, jint, jint); + +JNIEXPORT jbyte JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glIsList(JNIEnv *, jobject, jint); +JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glNewList(JNIEnv *, jobject, jint, jint); +JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glCallList(JNIEnv *, jobject, jint); +JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glEndList(JNIEnv *, jobject); +JNIEXPORT jint JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glGenLists(JNIEnv *, jobject, jint); +JNIEXPORT void JNICALL Java_org_apache_harmony_awt_gl_opengl_GL_glDeleteLists(JNIEnv *, jobject, jint, jint); + #ifdef __cplusplus } #endif