2006-06-05 Sven de Marothy <[EMAIL PROTECTED]>
* gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
* include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c
New files.
* gnu/java/awt/peer/gtk/GdkFontPeer.java
(getGlyphVector): Removed native method.
(createGlyphVector, getStringBounds): Use new GV class.
* include/Makefile.am
* native/jni/gtk-peer/Makefile.am
Add new files.
* include/gnu_java_awt_peer_gtk_GdkFontPeer.h
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c
(getGlyphVector): Removed native method.
? gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
? include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h
? native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c
Index: gnu/java/awt/peer/gtk/GdkFontPeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java,v
retrieving revision 1.14
diff -U3 -r1.14 GdkFontPeer.java
--- gnu/java/awt/peer/gtk/GdkFontPeer.java 30 May 2006 22:36:32 -0000 1.14
+++ gnu/java/awt/peer/gtk/GdkFontPeer.java 7 Jun 2006 13:45:10 -0000
@@ -47,8 +47,10 @@
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
+import java.awt.font.GlyphMetrics;
import java.awt.font.LineMetrics;
import java.awt.geom.Rectangle2D;
+import java.awt.geom.Point2D;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Locale;
@@ -234,23 +236,18 @@
return -1;
}
- private native GdkGlyphVector getGlyphVector(String txt,
- Font f,
- FontRenderContext ctx);
-
public GlyphVector createGlyphVector (Font font,
FontRenderContext ctx,
CharacterIterator i)
{
- return getGlyphVector(buildString (i), font, ctx);
+ return new FreetypeGlyphVector(font, buildString (i), ctx);
}
public GlyphVector createGlyphVector (Font font,
FontRenderContext ctx,
int[] glyphCodes)
{
- return null;
- // return new GdkGlyphVector (font, this, ctx, glyphCodes);
+ return new FreetypeGlyphVector(font, glyphCodes, ctx);
}
public byte getBaselineFor (Font font, char c)
@@ -338,7 +335,9 @@
public Rectangle2D getStringBounds (Font font, CharacterIterator ci,
int begin, int limit, FontRenderContext frc)
{
- GdkGlyphVector gv = getGlyphVector(buildString (ci, begin, limit), font, frc);
+ GlyphVector gv = new FreetypeGlyphVector( font,
+ buildString(ci, begin, limit),
+ frc);
return gv.getVisualBounds();
}
@@ -373,5 +372,4 @@
// the metrics cache.
return Toolkit.getDefaultToolkit().getFontMetrics (font);
}
-
}
Index: include/Makefile.am
===================================================================
RCS file: /sources/classpath/classpath/include/Makefile.am,v
retrieving revision 1.63
diff -U3 -r1.63 Makefile.am
--- include/Makefile.am 6 Jun 2006 10:04:15 -0000 1.63
+++ include/Makefile.am 7 Jun 2006 13:45:11 -0000
@@ -41,6 +41,7 @@
$(top_srcdir)/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_ComponentGraphics.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_ComponentGraphicsCopy.h \
+$(top_srcdir)/include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkFontPeer.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkPixbufDecoder.h \
Index: include/gnu_java_awt_peer_gtk_GdkFontPeer.h
===================================================================
RCS file: /sources/classpath/classpath/include/gnu_java_awt_peer_gtk_GdkFontPeer.h,v
retrieving revision 1.8
diff -U3 -r1.8 gnu_java_awt_peer_gtk_GdkFontPeer.h
--- include/gnu_java_awt_peer_gtk_GdkFontPeer.h 29 May 2006 16:14:59 -0000 1.8
+++ include/gnu_java_awt_peer_gtk_GdkFontPeer.h 7 Jun 2006 13:45:11 -0000
@@ -18,7 +18,6 @@
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics (JNIEnv *env, jobject, jstring, jdoubleArray);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_releasePeerGraphicsResource (JNIEnv *env, jobject);
JNIEXPORT jbyteArray JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTrueTypeTable (JNIEnv *env, jobject, jbyte, jbyte, jbyte, jbyte);
-JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector (JNIEnv *env, jobject, jstring, jobject, jobject);
#ifdef __cplusplus
}
Index: native/jni/gtk-peer/Makefile.am
===================================================================
RCS file: /sources/classpath/classpath/native/jni/gtk-peer/Makefile.am,v
retrieving revision 1.44
diff -U3 -r1.44 Makefile.am
--- native/jni/gtk-peer/Makefile.am 6 Jun 2006 10:04:15 -0000 1.44
+++ native/jni/gtk-peer/Makefile.am 7 Jun 2006 13:45:11 -0000
@@ -5,6 +5,7 @@
gnu_java_awt_peer_gtk_CairoGraphics2D.c \
gnu_java_awt_peer_gtk_ComponentGraphics.c \
gnu_java_awt_peer_gtk_ComponentGraphicsCopy.c \
+ gnu_java_awt_peer_gtk_FreetypeGlyphVector.c \
gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c \
gnu_java_awt_peer_gtk_GdkFontPeer.c \
gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c \
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c
===================================================================
RCS file: /sources/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c,v
retrieving revision 1.18
diff -U3 -r1.18 gnu_java_awt_peer_gtk_GdkFontPeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c 29 May 2006 16:14:59 -0000 1.18
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c 7 Jun 2006 13:45:11 -0000
@@ -59,8 +59,6 @@
java_awt_font_HANGING_BASELINE = 2
};
-static jmethodID glyphVector_ctor;
-static jclass glyphVector_class;
static PangoAttrList *attrs = NULL;
JNIEXPORT void JNICALL
@@ -68,16 +66,6 @@
(JNIEnv *env, jclass clazz)
{
NSA_FONT_INIT (env, clazz);
-
- glyphVector_class = (*env)->FindClass
- (env, "gnu/java/awt/peer/gtk/GdkGlyphVector");
-
- glyphVector_class = (*env)->NewGlobalRef
- (env, glyphVector_class);
-
- glyphVector_ctor = (*env)->GetMethodID
- (env, glyphVector_class, "<init>",
- "([D[ILjava/awt/Font;Ljava/awt/font/FontRenderContext;)V");
}
JNIEXPORT void JNICALL
@@ -140,123 +128,6 @@
gdk_threads_leave();
}
-JNIEXPORT jobject JNICALL
-Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector
- (JNIEnv *env, jobject self,
- jstring chars,
- jobject font,
- jobject fontRenderContext)
-{
- struct peerfont *pfont = NULL;
- GList *items = NULL;
- GList *i = NULL;
- gchar *str = NULL;
- int len = 0;
- int j = 0;
- double *native_extents = NULL;
- int *native_codes = NULL;
- jintArray java_codes = NULL;
- jdoubleArray java_extents = NULL;
-
- gdk_threads_enter ();
-
- pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self);
- g_assert (pfont != NULL);
-
- len = (*cp_gtk_gdk_env())->GetStringUTFLength (env, chars);
- str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL);
- g_assert (str != NULL);
-
- if (attrs == NULL)
- attrs = pango_attr_list_new ();
-
- if (len > 0 && str[len-1] == '\0')
- len--;
-
- items = pango_itemize (pfont->ctx, str, 0, len, attrs, NULL);
-
- i = g_list_first (items);
-
- if (i == NULL)
- {
- java_extents = (*env)->NewDoubleArray (env, 0);
- java_codes = (*env)->NewIntArray (env, 0);
- }
- else
- {
- PangoGlyphString *glyphs;
- PangoItem *item = (PangoItem *)i->data;
-
- pango_context_set_font_description (pfont->ctx, pfont->desc);
- pango_context_set_language (pfont->ctx, gtk_get_default_language());
- pango_context_load_font (pfont->ctx, pfont->desc);
-
- glyphs = pango_glyph_string_new ();
- g_assert (glyphs != NULL);
-
- pango_shape (str + item->offset, item->length,
- &(item->analysis), glyphs);
-
- if (glyphs->num_glyphs > 0)
- {
- int x = 0;
- double scale = ((double) PANGO_SCALE);
-
- java_extents = (*env)->NewDoubleArray (env, glyphs->num_glyphs * NUM_GLYPH_METRICS);
- java_codes = (*env)->NewIntArray (env, glyphs->num_glyphs);
-
- native_extents = (*env)->GetDoubleArrayElements (env, java_extents, NULL);
- native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL);
-
- for (j = 0; j < glyphs->num_glyphs; ++j)
- {
- PangoRectangle ink;
- PangoRectangle logical;
- PangoGlyphGeometry *geom = &glyphs->glyphs[j].geometry;
-
- pango_font_get_glyph_extents (pfont->font,
- glyphs->glyphs[j].glyph,
- &ink, &logical);
-
- native_codes[j] = glyphs->glyphs[j].glyph;
-
- native_extents[ GLYPH_LOG_X(j) ] = (logical.x) / scale;
- native_extents[ GLYPH_LOG_Y(j) ] = (- logical.y) / scale;
- native_extents[ GLYPH_LOG_WIDTH(j) ] = (logical.width) / scale;
- native_extents[ GLYPH_LOG_HEIGHT(j) ] = (logical.height) / scale;
-
- native_extents[ GLYPH_INK_X(j) ] = (ink.x) / scale;
- native_extents[ GLYPH_INK_Y(j) ] = (- ink.y) / scale;
- native_extents[ GLYPH_INK_WIDTH(j) ] = (ink.width) / scale;
- native_extents[ GLYPH_INK_HEIGHT(j) ] = (ink.height) / scale;
-
- native_extents[ GLYPH_POS_X(j) ] = (x + geom->x_offset) / scale;
- native_extents[ GLYPH_POS_Y(j) ] = ( - geom->y_offset) / scale;
-
- x += geom->width;
- }
- (*env)->ReleaseDoubleArrayElements (env, java_extents, native_extents, 0);
- (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0);
- }
-
- pango_glyph_string_free (glyphs);
- }
-
- (*env)->ReleaseStringUTFChars (env, chars, str);
-
- for (i = g_list_first (items); i != NULL; i = g_list_next (i))
- pango_item_free(i->data);
-
- g_list_free (items);
-
- gdk_threads_leave ();
-
- return (*env)->NewObject (env,
- glyphVector_class,
- glyphVector_ctor,
- java_extents, java_codes,
- font, fontRenderContext);
-}
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics
/* FreetypeGlyphVector.java
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath 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 for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Font;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.GeneralPath;
import java.awt.font.GlyphJustificationInfo;
import java.awt.font.GlyphMetrics;
import java.awt.font.GlyphVector;
import java.awt.font.FontRenderContext;
public class FreetypeGlyphVector extends GlyphVector
{
/**
* The associated font and its peer.
*/
private Font font;
private GdkFontPeer peer; // ATTN: Accessed from native code.
/**
* The string represented by this GlyphVector.
*/
private String s;
/**
* The font render context
*/
private FontRenderContext frc;
/**
* The total # of glyphs.
*/
private int nGlyphs;
/**
* The glyph codes
*/
private int[] glyphCodes;
/**
* Glyph transforms. (de facto only the translation is used)
*/
private AffineTransform[] glyphTransforms;
/**
* Create a glyphvector from a given (Freetype) font and a String.
*/
public FreetypeGlyphVector(Font f, String s, FontRenderContext frc)
{
this.s = s;
this.font = f;
this.frc = frc;
if( !(font.getPeer() instanceof GdkFontPeer ) )
throw new IllegalArgumentException("Not a valid font.");
peer = (GdkFontPeer)font.getPeer();
getGlyphs();
performDefaultLayout();
}
/**
* Create a glyphvector from a given set of glyph codes.
*/
public FreetypeGlyphVector(Font f, int[] codes, FontRenderContext frc)
{
this.s = s;
this.font = f;
this.frc = frc;
if( !(font.getPeer() instanceof GdkFontPeer ) )
throw new IllegalArgumentException("Not a valid font.");
peer = (GdkFontPeer)font.getPeer();
glyphCodes = new int[ codes.length ];
System.arraycopy(codes, 0, glyphCodes, 0, codes.length);
nGlyphs = glyphCodes.length;
performDefaultLayout();
}
/**
* Create the array of glyph codes.
*/
private void getGlyphs()
{
nGlyphs = s.codePointCount( 0, s.length() );
glyphCodes = new int[ nGlyphs ];
int stringIndex = 0;
for(int i = 0; i < nGlyphs; i++)
{
glyphCodes[i] = getGlyph( s.codePointAt(stringIndex) );
// UTF32 surrogate handling
if( s.codePointAt( stringIndex ) != (int)s.charAt( stringIndex ) )
stringIndex ++;
stringIndex ++;
}
}
/**
* Returns the glyph code within the font for a given character
*/
public native int getGlyph(int codepoint);
/**
* Returns the kerning of a glyph pair
*/
private native Point2D getKerning(int leftGlyph, int rightGlyph);
private native double[] getMetricsNative( int glyphCode );
private native GeneralPath getGlyphOutlineNative(int glyphIndex);
/**
* Duh, compares two instances.
*/
public boolean equals(GlyphVector gv)
{
if( ! (gv instanceof FreetypeGlyphVector) )
return false;
return (((FreetypeGlyphVector)gv).font.equals(font) &&
((FreetypeGlyphVector)gv).frc.equals(frc)
&& ((FreetypeGlyphVector)gv).s.equals(s));
}
/**
* Returns the associated Font
*/
public Font getFont()
{
return font;
}
/**
* Returns the associated FontRenderContext
*/
public FontRenderContext getFontRenderContext()
{
return frc;
}
/**
* Layout the glyphs.
*/
public void performDefaultLayout()
{
glyphTransforms = new AffineTransform[ nGlyphs ];
double x = 0;
for(int i = 0; i < nGlyphs; i++)
{
GlyphMetrics gm = getGlyphMetrics( i );
Rectangle2D r = gm.getBounds2D();
glyphTransforms[ i ] = AffineTransform.getTranslateInstance(x, 0);
x += gm.getAdvanceX();
}
}
/**
* Returns the code of the glyph at glyphIndex;
*/
public int getGlyphCode(int glyphIndex)
{
return glyphCodes[ glyphIndex ];
}
/**
* Returns multiple glyphcodes.
*/
public int[] getGlyphCodes(int beginGlyphIndex, int numEntries,
int[] codeReturn)
{
int[] rval;
if( codeReturn == null )
rval = new int[ numEntries ];
else
rval = codeReturn;
System.arraycopy(glyphCodes, beginGlyphIndex, rval, 0, numEntries);
return rval;
}
/**
* FIXME: Implement me.
*/
public Shape getGlyphLogicalBounds(int glyphIndex)
{
GlyphMetrics gm = getGlyphMetrics( glyphIndex );
if( gm == null )
return null;
Rectangle2D r = gm.getBounds2D();
return new Rectangle2D.Double( r.getX() - gm.getLSB(), r.getY(),
gm.getAdvanceX(), r.getHeight() );
}
/**
* Returns the metrics of a single glyph.
*/
public GlyphMetrics getGlyphMetrics(int glyphIndex)
{
double[] val = getMetricsNative( glyphCodes[ glyphIndex ] );
if( val == null )
return null;
return new GlyphMetrics( true, (float)val[1], (float)val[2],
new Rectangle2D.Double( val[3], val[4],
val[5], val[6] ),
GlyphMetrics.STANDARD );
}
/**
* Returns the outline of a single glyph.
*/
public Shape getGlyphOutline(int glyphIndex)
{
GeneralPath gp = getGlyphOutlineNative( glyphCodes[ glyphIndex ] );
gp.transform( glyphTransforms[ glyphIndex ] );
return gp;
}
/**
* Returns the position of a single glyph.
*/
public Point2D getGlyphPosition(int glyphIndex)
{
return glyphTransforms[ glyphIndex ].transform( new Point2D.Double(0, 0),
null );
}
/**
* Returns the positions of multiple glyphs.
*/
public float[] getGlyphPositions(int beginGlyphIndex, int numEntries,
float[] positionReturn)
{
float[] rval;
if( positionReturn == null )
rval = new float[2 * numEntries];
else
rval = positionReturn;
for( int i = beginGlyphIndex; i < numEntries; i++ )
{
Point2D p = getGlyphPosition( i );
rval[i * 2] = (float)p.getX();
rval[i * 2 + 1] = (float)p.getY();
}
return rval;
}
/**
* Returns the transform of a glyph.
*/
public AffineTransform getGlyphTransform(int glyphIndex)
{
return new AffineTransform( glyphTransforms[ glyphIndex ] );
}
/**
* Returns the visual bounds of a glyph
* May be off by a pixel or two due to hinting/rasterization.
*/
public Shape getGlyphVisualBounds(int glyphIndex)
{
return getGlyphOutline( glyphIndex ).getBounds2D();
}
/**
* Return the logical bounds of the whole thing.
*/
public Rectangle2D getLogicalBounds()
{
if( nGlyphs == 0 )
return new Rectangle2D.Double(0, 0, 0, 0);
Rectangle2D rect = (Rectangle2D)getGlyphLogicalBounds( 0 );
for( int i = 1; i < nGlyphs; i++ )
rect = rect.createUnion( (Rectangle2D)getGlyphLogicalBounds( i ) );
return rect;
}
/**
* Returns the number of glyphs.
*/
public int getNumGlyphs()
{
return glyphCodes.length;
}
/**
* Returns the outline of the entire GlyphVector.
*/
public Shape getOutline()
{
GeneralPath path = new GeneralPath();
for( int i = 0; i < getNumGlyphs(); i++ )
path.append( getGlyphOutline( i ), false );
return path;
}
/**
* TODO:
* FreeType does not currently have an API for the JSTF table. We should
* probably get the table ourselves from FT and pass it to some parser
* which the native font peers will need.
*/
public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex)
{
return null;
}
/**
* Returns the outline of the entire vector, drawn at (x,y).
*/
public Shape getOutline(float x, float y)
{
AffineTransform tx = AffineTransform.getTranslateInstance( x, y );
return tx.createTransformedShape( getOutline() );
}
/**
* Returns the visual bounds of the entire GlyphVector.
* May be off by a pixel or two due to hinting/rasterization.
*/
public Rectangle2D getVisualBounds()
{
return getOutline().getBounds2D();
}
/**
* Sets the position of a glyph.
*/
public void setGlyphPosition(int glyphIndex, Point2D newPos)
{
// FIXME: Scaling, etc.?
glyphTransforms[ glyphIndex ].setToTranslation( newPos.getX(),
newPos.getY() );
}
/**
* Sets the transform of a single glyph.
*/
public void setGlyphTransform(int glyphIndex, AffineTransform newTX)
{
glyphTransforms[ glyphIndex ].setTransform( newTX );
}
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#ifndef __gnu_java_awt_peer_gtk_FreetypeGlyphVector__
#define __gnu_java_awt_peer_gtk_FreetypeGlyphVector__
#include <jni.h>
#ifdef __cplusplus
extern "C"
{
#endif
JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyph (JNIEnv *env, jobject, jint);
JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning (JNIEnv *env, jobject, jint, jint);
JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative (JNIEnv *env, jobject, jint);
JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative (JNIEnv *env, jobject, jint);
#ifdef __cplusplus
}
#endif
#endif /* __gnu_java_awt_peer_gtk_FreetypeGlyphVector__ */
/* gnu_java_awt_FreetypeGlyphVector.c
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath 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 for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
#include <jni.h>
#include <gtk/gtk.h>
#include <string.h>
#include <pango/pango.h>
#include <pango/pangoft2.h>
#include <pango/pangofc-font.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include "native_state.h"
#include "gdkfont.h"
#include "gnu_java_awt_peer_gtk_FreetypeGlyphVector.h"
#include "cairographics2d.h"
typedef struct gp
{
JNIEnv *env;
jobject obj;
double px;
double py;
double sx;
double sy;
} generalpath ;
static PangoFcFont *
getFont(JNIEnv *env, jobject obj)
{
jfieldID fid;
jobject data;
jclass cls;
struct peerfont *pfont;
cls = (*env)->GetObjectClass (env, obj);
fid = (*env)->GetFieldID (env, cls, "peer",
"Lgnu/java/awt/peer/gtk/GdkFontPeer;");
g_assert (fid != 0);
data = (*env)->GetObjectField (env, obj, fid);
g_assert (data != NULL);
pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, data);
g_assert (pfont != NULL);
g_assert (pfont->font != NULL);
return (PangoFcFont *)pfont->font;
}
JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyph
(JNIEnv *env, jobject obj, jint codepoint)
{
FT_Face ft_face;
jint glyph_index;
PangoFcFont *font;
font = getFont(env, obj);
ft_face = pango_fc_font_lock_face( font );
g_assert (ft_face != NULL);
glyph_index = FT_Get_Char_Index( ft_face, codepoint );
pango_fc_font_unlock_face (font);
return glyph_index;
}
JNIEXPORT jobject JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getKerning
(JNIEnv *env, jobject obj, jint rightGlyph, jint leftGlyph)
{
FT_Face ft_face;
FT_Vector kern;
jclass cls;
jmethodID method;
jvalue values[2];
PangoFcFont *font;
font = getFont(env, obj);
ft_face = pango_fc_font_lock_face( font );
g_assert (ft_face != NULL);
FT_Get_Kerning( ft_face, rightGlyph, leftGlyph, FT_KERNING_DEFAULT, &kern );
pango_fc_font_unlock_face( font );
values[0].d = (jdouble)kern.x/64.0;
values[1].d = (jdouble)kern.y/64.0;
cls = (*env)->FindClass (env, "java/awt/geom/Point2D.Double");
method = (*env)->GetMethodID (env, cls, "<init>", "(DD)V");
return (*env)->NewObjectA(env, cls, method, values);
}
JNIEXPORT jdoubleArray JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative
(JNIEnv *env, jobject obj, jint glyphIndex )
{
FT_Face ft_face;
jdouble *values;
jdoubleArray retArray = NULL;
PangoFcFont *font;
FT_BBox acbox;
font = getFont(env, obj);
ft_face = pango_fc_font_lock_face( font );
g_assert (ft_face != NULL);
FT_Set_Transform( ft_face, NULL, NULL );
if( FT_Load_Glyph( ft_face, glyphIndex, FT_LOAD_DEFAULT ) != 0 )
{
pango_fc_font_unlock_face( font );
printf("Couldn't load glyph %i\n", glyphIndex);
return NULL;
}
retArray = (*env)->NewDoubleArray (env, 8);
values = (*env)->GetDoubleArrayElements (env, retArray, NULL);
values[0] = 0;
values[1] = (jdouble)ft_face->glyph->advance.x/64.0;
values[2] = (jdouble)ft_face->glyph->advance.y/64.0;
values[3] = (jdouble)ft_face->glyph->metrics.horiBearingX/64.0;
values[4] = -(jdouble)ft_face->glyph->metrics.horiBearingY/64.0;
values[5] = (jdouble)ft_face->glyph->metrics.width/64.0;
values[6] = (jdouble)ft_face->glyph->metrics.height/64.0;
values[7] = 0;
(*env)->ReleaseDoubleArrayElements (env, retArray, values, 0);
pango_fc_font_unlock_face( font );
return retArray;
}
/* GetOutline code follows ****************************/
/********* Freetype callback functions *****************************/
static int _moveTo( const FT_Vector* to,
void *p)
{
JNIEnv *env;
jobject obj;
jclass cls;
jmethodID method;
jvalue values[2];
generalpath *path = (generalpath *) p;
env = path->env;
obj = path->obj;
values[0].f = (jfloat)(to->x * path->sx + path->px);
values[1].f = (jfloat)(to->y * path->sy + path->py);
cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
method = (*env)->GetMethodID (env, cls, "moveTo", "(FF)V");
(*env)->CallVoidMethodA(env, obj, method, values );
return 0;
}
static int _lineTo( const FT_Vector* to,
void *p)
{
JNIEnv *env;
jobject obj;
jclass cls;
jmethodID method;
jvalue values[2];
generalpath *path = (generalpath *) p;
env = path->env;
obj = path->obj;
values[0].f = (jfloat)(to->x * path->sx + path->px);
values[1].f = (jfloat)(to->y * path->sy + path->py);
cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
method = (*env)->GetMethodID (env, cls, "lineTo", "(FF)V");
(*env)->CallVoidMethodA(env, obj, method, values );
return 0;
}
static int _quadTo( const FT_Vector* cp,
const FT_Vector* to,
void *p)
{
JNIEnv *env;
jobject obj;
jclass cls;
jmethodID method;
jvalue values[4];
generalpath *path = (generalpath *) p;
env = path->env;
obj = path->obj;
values[0].f = (jfloat)(cp->x * path->sx + path->px);
values[1].f = (jfloat)(cp->y * path->sy + path->py);
values[2].f = (jfloat)(to->x * path->sx + path->px);
values[3].f = (jfloat)(to->y * path->sy + path->py);
cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
method = (*env)->GetMethodID (env, cls, "quadTo", "(FFFF)V");
(*env)->CallVoidMethodA(env, obj, method, values );
return 0;
}
static int _curveTo( const FT_Vector* cp1,
const FT_Vector* cp2,
const FT_Vector* to,
void *p)
{
JNIEnv *env;
jobject obj;
jclass cls;
jmethodID method;
jvalue values[6];
generalpath *path = (generalpath *) p;
env = path->env;
obj = path->obj;
values[0].f = (jfloat)(cp1->x * path->sx + path->px);
values[1].f = (jfloat)(cp1->y * path->sy + path->py);
values[2].f = (jfloat)(cp2->x * path->sx + path->px);
values[3].f = (jfloat)(cp2->y * path->sy + path->py);
values[4].f = (jfloat)(to->x * path->sx + path->px);
values[5].f = (jfloat)(to->y * path->sy + path->py);
cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
method = (*env)->GetMethodID (env, cls, "curveTo", "(FFFFFF)V");
(*env)->CallVoidMethodA(env, obj, method, values );
return 0;
}
JNIEXPORT jobject JNICALL
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative
(JNIEnv *env, jobject obj, jint glyphIndex)
{
generalpath *path;
jobject gp;
FT_Outline_Funcs ftCallbacks =
{
(FT_Outline_MoveToFunc) _moveTo,
(FT_Outline_LineToFunc) _lineTo,
(FT_Outline_ConicToFunc) _quadTo,
(FT_Outline_CubicToFunc) _curveTo,
0,
0
};
PangoFcFont *font;
FT_Face ft_face;
FT_Glyph glyph;
font = getFont(env, obj);
ft_face = pango_fc_font_lock_face( font );
g_assert (ft_face != NULL);
path = g_malloc0 (sizeof (generalpath));
g_assert(path != NULL);
path->env = env;
path->px = path->py = 0.0;
path->sx = 1.0/64.0;
path->sy = -1.0/64.0;
{ /* create a GeneralPath instance */
jclass cls;
jmethodID method;
cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
method = (*env)->GetMethodID (env, cls, "<init>", "()V");
gp = path->obj = (*env)->NewObject (env, cls, method);
}
if(FT_Load_Glyph(ft_face,
(FT_UInt)(glyphIndex),
FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP) != 0)
{
pango_fc_font_unlock_face( font );
g_free(path);
return NULL;
}
FT_Get_Glyph( ft_face->glyph, &glyph );
FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline),
&ftCallbacks, path);
FT_Done_Glyph( glyph );
pango_fc_font_unlock_face( font );
g_free(path);
return gp;
}