changeset 4191:21e5afedadfd

RT-23467: Evaluate Native Text Engines. Initial Linux implementation (freetype and pango). Native build missing
author Felipe Heidrich <felipe.heidrich@oracle.com>
date Fri, 05 Jul 2013 10:54:43 -0700
parents 3bde7459ce4d
children 89ae1b941f13
files modules/graphics/src/main/java/com/sun/javafx/font/pango/FTDisposer.java modules/graphics/src/main/java/com/sun/javafx/font/pango/FTFontFile.java modules/graphics/src/main/java/com/sun/javafx/font/pango/FTFontStrike.java modules/graphics/src/main/java/com/sun/javafx/font/pango/FTGlyph.java modules/graphics/src/main/java/com/sun/javafx/font/pango/FT_Bitmap.java modules/graphics/src/main/java/com/sun/javafx/font/pango/FT_GlyphSlotRec.java modules/graphics/src/main/java/com/sun/javafx/font/pango/FT_Glyph_Metrics.java modules/graphics/src/main/java/com/sun/javafx/font/pango/FT_Matrix.java modules/graphics/src/main/java/com/sun/javafx/font/pango/OS.java modules/graphics/src/main/java/com/sun/javafx/font/pango/PangoFactory.java modules/graphics/src/main/java/com/sun/javafx/font/pango/PangoGlyphInfo.java modules/graphics/src/main/java/com/sun/javafx/font/pango/PangoGlyphLayout.java modules/graphics/src/main/java/com/sun/javafx/font/pango/PangoGlyphString.java modules/graphics/src/main/native-font/freetype.c modules/graphics/src/main/native-font/pango.c
diffstat 15 files changed, 2163 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/FTDisposer.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+import com.sun.javafx.font.DisposerRecord;
+import com.sun.javafx.font.PrismFontFactory;
+
+class FTDisposer implements DisposerRecord  {
+    long library;
+    long face;
+
+    FTDisposer(long library, long face) {
+        this.library = library;
+        this.face = face;
+    }
+
+    public synchronized void dispose() {
+        if (face != 0) {
+            OS.FT_Done_Face(face);
+            if (PrismFontFactory.debugFonts) {
+                System.err.println("Done Face=" + face);
+            }
+            face = 0;
+        }
+        if (library != 0) {
+            OS.FT_Done_FreeType(library);
+            if (PrismFontFactory.debugFonts) {
+                System.err.println("Done Library=" + library);
+            }
+            library = 0;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/FTFontFile.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+import com.sun.javafx.font.Disposer;
+import com.sun.javafx.font.FontResource;
+import com.sun.javafx.font.FontStrikeDesc;
+import com.sun.javafx.font.PrismFontFactory;
+import com.sun.javafx.font.PrismFontFile;
+import com.sun.javafx.font.PrismFontStrike;
+import com.sun.javafx.geom.Path2D;
+import com.sun.javafx.geom.transform.BaseTransform;
+
+class FTFontFile extends PrismFontFile {
+    /*
+     * Font files can be accessed by several threads. In general this are the
+     * JFX thread (measuring) and the Prism thread (rendering). But, if a Text
+     * node is no connected a Scene it can be used in any user thread, thus a
+     * font resource can be accessed from any thread.
+     *
+     * Freetype resources are not thread safe. In this implementation each font
+     * resources has its own FT_Face and FT_Library, and while it permits these
+     * resources be used by different threads it does not allow concurrent access.
+     * This is enforced by converging all operation (from FTFontStrike and
+     * FTGlyph) to this object and synchronizing the access to the native
+     * resources using the same lock.
+     */
+    private long library;
+    private long face;
+    private FTDisposer disposer;
+
+    FTFontFile(String name, String filename, int fIndex, boolean register,
+               boolean embedded, boolean copy, boolean tracked) throws Exception {
+        super(name, filename, fIndex, register, embedded, copy, tracked);
+        init();
+    }
+
+    private synchronized void init() throws Exception {
+        long[] ptr = new long[1];
+        int error = OS.FT_Init_FreeType(ptr);
+        if (error != 0) {
+            throw new Exception("FT_Init_FreeType Failed error " + error);
+        }
+        library = ptr[0];
+        if (PangoFactory.LCD_SUPPORT) {
+            OS.FT_Library_SetLcdFilter(library, OS.FT_LCD_FILTER_DEFAULT);
+        }
+
+        String file = getFileName();
+        int fontIndex = getFontIndex();
+        /* Freetype expects 'a standard C string' */
+        byte[] buffer = (file+"\0").getBytes();
+        error = OS.FT_New_Face(library, buffer, fontIndex, ptr);
+        if (error != 0) {
+            throw new Exception("FT_New_Face Failed error " + error +
+                                " Font File " + file +
+                                " Font Index " + fontIndex);
+        }
+        face = ptr[0];
+
+        if (!isRegistered()) {
+            disposer = new FTDisposer(library, face);
+            Disposer.addRecord(this, disposer);
+        }
+    }
+
+    /* This is called only for fonts where a temp file was created */
+    @Override
+    protected synchronized void disposeOnShutdown() {
+        if (face != 0) {
+            OS.FT_Done_Face(face);
+            if (PrismFontFactory.debugFonts) {
+                System.err.println("Done Face=" + face);
+            }
+            face = 0;
+        }
+        if (library != 0) {
+            OS.FT_Done_FreeType(library);
+            if (PrismFontFactory.debugFonts) {
+                System.err.println("Done Library=" + library);
+            }
+            library = 0;
+        }
+        if (disposer != null) {
+            disposer.library = 0;
+            disposer.face = 0;
+            disposer = null;
+        }
+    }
+
+    @Override
+    protected PrismFontStrike<?> createStrike(float size, BaseTransform transform,
+                                              int aaMode, FontStrikeDesc desc) {
+        return new FTFontStrike(this, size, transform, aaMode, desc);
+    }
+
+    @Override
+    protected synchronized int[] createGlyphBoundingBox(int gc) {
+        int flags = OS.FT_LOAD_NO_SCALE;
+        OS.FT_Load_Glyph(face, gc, flags);
+        FT_GlyphSlotRec glyphRec = OS.getGlyphSlot(face);
+        FT_Glyph_Metrics gm = glyphRec.metrics;
+        int[] bbox = new int[4];
+        bbox[0] = (int)gm.horiBearingX;
+        bbox[1] = (int)(gm.horiBearingY - gm.height);
+        bbox[2] = (int)(gm.horiBearingX + gm.width);
+        bbox[3] = (int)gm.horiBearingY;
+        return bbox;
+    }
+
+    synchronized Path2D createGlyphOutline(int gc, float size) {
+        int size26dot6 = (int)(size * 64);
+        OS.FT_Set_Char_Size(face, 0, size26dot6, 72, 72);
+        int flags = OS.FT_LOAD_NO_HINTING | OS.FT_LOAD_NO_BITMAP | OS.FT_LOAD_IGNORE_TRANSFORM;
+        OS.FT_Load_Glyph(face, gc, flags);
+        return OS.FT_Outline_Decompose(face);
+    }
+
+    synchronized void initGlyph(FTGlyph glyph, FTFontStrike strike) {
+        int size26dot6 = (int)(strike.getSize() * 64);
+        OS.FT_Set_Char_Size(face, 0, size26dot6, 72, 72);
+
+        boolean lcd = strike.getAAMode() == FontResource.AA_LCD &&
+                      PangoFactory.LCD_SUPPORT;
+
+        int flags = OS.FT_LOAD_RENDER | OS.FT_LOAD_NO_HINTING;
+        FT_Matrix matrix = strike.matrix;
+        if (matrix != null) {
+            OS.FT_Set_Transform(face, matrix, 0, 0);
+        } else {
+            flags |= OS.FT_LOAD_IGNORE_TRANSFORM;
+        }
+        if (lcd) {
+            flags |= OS.FT_LOAD_TARGET_LCD;
+        } else {
+            flags |= OS.FT_LOAD_TARGET_NORMAL;
+        }
+
+        int glyphCode = glyph.getGlyphCode();
+        int error = OS.FT_Load_Glyph(face, glyphCode, flags);
+        if (error != 0) {
+            if (PrismFontFactory.debugFonts) {
+                System.err.println("FT_Load_Glyph failed " + error +
+                                   " glyph code " + glyphCode +
+                                   " load falgs " + flags);
+            }
+            return;
+        }
+
+        FT_GlyphSlotRec glyphRec = OS.getGlyphSlot(face);
+        FT_Bitmap bitmap = glyphRec.bitmap;
+        int width = bitmap.width;
+        int height = bitmap.rows;
+        int pitch = bitmap.pitch;
+        byte[] buffer;
+        if (width != 0 && height != 0) {
+            buffer = OS.getBitmapData(face);
+            if (pitch != width) {
+                /* Common for LCD glyphs */
+                byte[] newBuffer = new byte[width * height];
+                int src = 0, dst = 0;
+                for (int y = 0; y < height; y++) {
+                    for (int x = 0; x < width; x++) {
+                        newBuffer[dst + x] = buffer[src + x];
+                    }
+                    dst += width;
+                    src += pitch;
+                }
+                buffer = newBuffer;
+            }
+        } else {
+            /* white space */
+            buffer = new byte[0];
+        }
+
+        glyph.buffer = buffer;
+        glyph.bitmap = bitmap;
+        glyph.bitmap_left = glyphRec.bitmap_left;
+        glyph.bitmap_top = glyphRec.bitmap_top;
+        glyph.advanceX = glyphRec.advance_x / 64f;    /* Fixed 26.6*/
+        glyph.advanceY = glyphRec.advance_y / 64f;
+        glyph.userAdvance = glyphRec.linearHoriAdvance / 65536.0f; /* Fixed 16.16 */
+        glyph.lcd = lcd;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/FTFontStrike.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+import com.sun.javafx.font.DisposerRecord;
+import com.sun.javafx.font.FontStrikeDesc;
+import com.sun.javafx.font.Glyph;
+import com.sun.javafx.font.PrismFontStrike;
+import com.sun.javafx.geom.Path2D;
+import com.sun.javafx.geom.transform.BaseTransform;
+
+class FTFontStrike extends PrismFontStrike<FTFontFile> {
+    FT_Matrix matrix;
+
+    protected FTFontStrike(FTFontFile fontResource, float size,
+                              BaseTransform tx, int aaMode,
+                              FontStrikeDesc desc) {
+        super(fontResource, size, tx, aaMode, desc);
+        float maxDim = 80f;
+        if (tx.isTranslateOrIdentity()) {
+            drawShapes = size > maxDim;
+        } else {
+            BaseTransform tx2d = getTransform();
+            matrix = new FT_Matrix();
+            /* Fixed 16.16 to int */
+            matrix.xx = (int)( tx2d.getMxx() * 65536.0f);
+            matrix.yx = (int)(-tx2d.getMyx() * 65536.0f); /*Inverted coordinates system */
+            matrix.xy = (int)(-tx2d.getMxy() * 65536.0f); /*Inverted coordinates system */
+            matrix.yy = (int)( tx2d.getMyy() * 65536.0f);
+
+            if (Math.abs(tx2d.getMxx() * size) > maxDim ||
+                Math.abs(tx2d.getMyx() * size) > maxDim ||
+                Math.abs(tx2d.getMxy() * size) > maxDim ||
+                Math.abs(tx2d.getMyy() * size) > maxDim)
+            {
+                drawShapes = true;
+            }
+        }
+    }
+
+    @Override
+    public boolean isSubPixelGlyph() {
+        return false;
+    }
+
+    @Override
+    protected DisposerRecord createDisposer(FontStrikeDesc desc) {
+        return null;
+    }
+
+    @Override
+    protected Glyph createGlyph(int glyphCode) {
+        return new FTGlyph(this, glyphCode, drawShapes);
+    }
+
+    @Override
+    protected Path2D createGlyphOutline(int glyphCode) {
+        FTFontFile fontResource = getFontResource();
+        return fontResource.createGlyphOutline(glyphCode, getSize());
+    }
+
+    void initGlyph(FTGlyph glyph) {
+        FTFontFile fontResource = getFontResource();
+        fontResource.initGlyph(glyph, this);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/FTGlyph.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+import com.sun.javafx.font.Glyph;
+import com.sun.javafx.geom.RectBounds;
+import com.sun.javafx.geom.Shape;
+
+class FTGlyph implements Glyph {
+    FTFontStrike strike;
+    int glyphCode;
+    byte[] buffer;
+    FT_Bitmap bitmap;
+    int bitmap_left;
+    int bitmap_top;
+    float advanceX;
+    float advanceY;
+    float userAdvance;
+    boolean lcd;
+
+    FTGlyph(FTFontStrike strike, int glyphCode, boolean drawAsShape) {
+        this.strike = strike;
+        this.glyphCode = glyphCode;
+    }
+
+    @Override
+    public int getGlyphCode() {
+        return glyphCode;
+    }
+
+    private void init() {
+        if (bitmap != null) return;
+        strike.initGlyph(this);
+    }
+
+    @Override
+    public RectBounds getBBox() {
+        float[] bb = new float[4];
+        FTFontFile fontResource = strike.getFontResource();
+        fontResource.getGlyphBoundingBox(glyphCode, strike.getSize(), bb);
+        return new RectBounds(bb[0], bb[1], bb[2], bb[3]);
+    }
+
+    @Override
+    public float getAdvance() {
+        init();
+        return userAdvance;
+    }
+
+    @Override
+    public Shape getShape() {
+        return strike.createGlyphOutline(glyphCode);
+    }
+
+    @Override
+    public byte[] getPixelData() {
+        init();
+        return buffer;
+    }
+
+    @Override
+    public byte[] getPixelData(float x, float y) {
+        init();
+        return buffer;
+    }
+
+    @Override
+    public float getPixelXAdvance() {
+        init();
+        return advanceX;
+    }
+
+    @Override
+    public float getPixelYAdvance() {
+        init();
+        return advanceY;
+    }
+
+    @Override
+    public int getWidth() {
+        init();
+        /* Note: In Freetype the width is byte based */
+        return bitmap.width;
+    }
+
+    @Override
+    public int getHeight() {
+        init();
+        return bitmap.rows;
+    }
+
+    @Override
+    public int getOriginX() {
+        init();
+        return bitmap_left;
+    }
+
+    @Override
+    public int getOriginY() {
+        init();
+        return -bitmap_top; /*Inverted coordinates system */
+    }
+
+    @Override
+    public boolean isLCDGlyph() {
+        return lcd;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/FT_Bitmap.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+class FT_Bitmap {
+    int rows;
+    int width;
+    int pitch;
+    long buffer;
+    short num_grays;
+    byte pixel_mode;
+    char palette_mode;
+    long palette;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/FT_GlyphSlotRec.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+class FT_GlyphSlotRec {
+    FT_Glyph_Metrics metrics = new FT_Glyph_Metrics();
+    long linearHoriAdvance;
+    long linearVertAdvance;
+    long advance_x;
+    long advance_y;
+    int format;
+    FT_Bitmap bitmap = new FT_Bitmap();
+    int bitmap_left;
+    int bitmap_top;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/FT_Glyph_Metrics.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+class FT_Glyph_Metrics {
+    long width;
+    long height;
+    long horiBearingX;
+    long horiBearingY;
+    long horiAdvance;
+    long vertBearingX;
+    long vertBearingY;
+    long vertAdvance;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/FT_Matrix.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+class FT_Matrix {
+    long xx;
+    long xy;
+    long yx;
+    long yy;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/OS.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import com.sun.glass.utils.NativeLibLoader;
+import com.sun.javafx.geom.Path2D;
+
+class OS {
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+           public Void run() {
+               NativeLibLoader.loadLibrary("javafx-font-pango");
+               return null;
+           }
+        });
+    }
+
+    /* Pango */
+    static final int PANGO_SCALE = 1024;
+    static final int PANGO_STRETCH_ULTRA_CONDENSED = 0x0;
+    static final int PANGO_STRETCH_EXTRA_CONDENSED = 0x1;
+    static final int PANGO_STRETCH_CONDENSED = 0x2;
+    static final int PANGO_STRETCH_SEMI_CONDENSED = 0x3;
+    static final int PANGO_STRETCH_NORMAL = 0x4;
+    static final int PANGO_STRETCH_SEMI_EXPANDED = 0x5;
+    static final int PANGO_STRETCH_EXPANDED = 0x6;
+    static final int PANGO_STRETCH_EXTRA_EXPANDED = 0x7;
+    static final int PANGO_STRETCH_ULTRA_EXPANDED = 0x8;
+    static final int PANGO_STYLE_ITALIC = 0x2;
+    static final int PANGO_STYLE_NORMAL = 0x0;
+    static final int PANGO_STYLE_OBLIQUE = 0x1;
+    static final int PANGO_WEIGHT_BOLD = 0x2bc;
+    static final int PANGO_WEIGHT_NORMAL = 0x190;
+
+    static final native long pango_ft2_font_map_new();
+    static final native long pango_font_map_create_context(long fontmap);
+    static final native long pango_font_describe(long font);
+    static final native long pango_font_description_new();
+    static final native void pango_font_description_free(long desc);
+    static final native String pango_font_description_get_family(long desc);
+    static final native int pango_font_description_get_stretch(long desc);
+    static final native int pango_font_description_get_style(long desc);
+    static final native int pango_font_description_get_weight(long desc);
+    static final native void pango_font_description_set_family(long desc, String family);
+    static final native void pango_font_description_set_absolute_size(long desc, double size);
+    static final native void pango_font_description_set_stretch(long desc, int stretch);
+    static final native void pango_font_description_set_style(long desc, int style);
+    static final native void pango_font_description_set_weight(long desc, int weight);
+    static final native long pango_attr_list_new();
+    static final native long pango_attr_font_desc_new(long desc);
+    static final native long pango_attr_fallback_new(boolean enable_fallback);
+    static final native void pango_attr_list_unref(long list);
+    static final native void pango_attr_list_insert(long list, long attr);
+    static final native long pango_itemize(long context, ByteBuffer text, int start_index, int length, long attrs, long cached_iter);
+    static final native PangoGlyphString pango_shape(ByteBuffer text, long pangoItem);
+    static final native void pango_item_free(long item);
+
+    /* Miscellaneous (glib, fontconfig) */
+    static final native int g_list_length(long list);
+    static final native long g_list_nth_data(long list, int n);
+    static final native void g_list_free(long list);
+    static final native void g_object_unref(long object);
+    static final native boolean FcConfigAppFontAddFile(long config, String file);
+
+    /* Freetype */
+    static final int FT_FACE_FLAG_SCALABLE          = 1 <<  0;
+    static final int FT_FACE_FLAG_FIXED_SIZES       = 1 <<  1;
+    static final int FT_FACE_FLAG_FIXED_WIDTH       = 1 <<  2;
+    static final int FT_FACE_FLAG_SFNT              = 1 <<  3;
+    static final int FT_FACE_FLAG_HORIZONTAL        = 1 <<  4;
+    static final int FT_FACE_FLAG_VERTICAL          = 1 <<  5;
+    static final int FT_FACE_FLAG_KERNING           = 1 <<  6;
+    static final int FT_FACE_FLAG_FAST_GLYPHS       = 1 <<  7;
+    static final int FT_FACE_FLAG_MULTIPLE_MASTERS  = 1 <<  8;
+    static final int FT_FACE_FLAG_GLYPH_NAMES       = 1 <<  9;
+    static final int FT_FACE_FLAG_EXTERNAL_STREAM   = 1 << 10;
+    static final int FT_FACE_FLAG_HINTER            = 1 << 11;
+    static final int FT_FACE_FLAG_CID_KEYED         = 1 << 12;
+    static final int FT_FACE_FLAG_TRICKY            = 1 << 13;
+    static final int FT_STYLE_FLAG_ITALIC  = 1 << 0;
+    static final int FT_STYLE_FLAG_BOLD    = 1 << 1;
+    static final int FT_RENDER_MODE_NORMAL = 0;
+    static final int FT_RENDER_MODE_LIGHT = 1;
+    static final int FT_RENDER_MODE_MONO = 2;
+    static final int FT_RENDER_MODE_LCD = 3;
+    static final int FT_RENDER_MODE_LCD_V = 4;
+    static final int FT_PIXEL_MODE_NONE = 0;
+    static final int FT_PIXEL_MODE_MONO = 1;
+    static final int FT_PIXEL_MODE_GRAY = 2;
+    static final int FT_PIXEL_MODE_GRAY2 = 3;
+    static final int FT_PIXEL_MODE_GRAY4 = 4;
+    static final int FT_PIXEL_MODE_LCD = 5;
+    static final int FT_PIXEL_MODE_LCD_V = 6;
+    static final int FT_LOAD_DEFAULT                      = 0x0;
+    static final int FT_LOAD_NO_SCALE                     = 1 << 0;
+    static final int FT_LOAD_NO_HINTING                   = 1 << 1;
+    static final int FT_LOAD_RENDER                       = 1 << 2;
+    static final int FT_LOAD_NO_BITMAP                    = 1 << 3;
+    static final int FT_LOAD_VERTICAL_LAYOUT              = 1 << 4;
+    static final int FT_LOAD_FORCE_AUTOHINT               = 1 << 5;
+    static final int FT_LOAD_CROP_BITMAP                  = 1 << 6;
+    static final int FT_LOAD_PEDANTIC                     = 1 << 7;
+    static final int FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH  = 1 << 9;
+    static final int FT_LOAD_NO_RECURSE                   = 1 << 10;
+    static final int FT_LOAD_IGNORE_TRANSFORM             = 1 << 11;
+    static final int FT_LOAD_MONOCHROME                   = 1 << 12;
+    static final int FT_LOAD_LINEAR_DESIGN                = 1 << 13;
+    static final int FT_LOAD_NO_AUTOHINT                  = 1 << 15;
+    static final int FT_LOAD_TARGET_NORMAL  = (FT_RENDER_MODE_NORMAL & 15 ) << 16;
+    static final int FT_LOAD_TARGET_LIGHT   = (FT_RENDER_MODE_LIGHT  & 15 ) << 16;
+    static final int FT_LOAD_TARGET_MONO    = (FT_RENDER_MODE_MONO   & 15 ) << 16;
+    static final int FT_LOAD_TARGET_LCD     = (FT_RENDER_MODE_LCD    & 15 ) << 16;
+    static final int FT_LOAD_TARGET_LCD_V   = (FT_RENDER_MODE_LCD_V  & 15 ) << 16;
+    static final int FT_LCD_FILTER_NONE    = 0;
+    static final int FT_LCD_FILTER_DEFAULT = 1;
+    static final int FT_LCD_FILTER_LIGHT   = 2;
+    static final int FT_LCD_FILTER_LEGACY  = 16;
+
+    static final int FT_LOAD_TARGET_MODE(int x) {
+        return (x >> 16 ) & 15;
+    }
+
+    static final native Path2D FT_Outline_Decompose(long face);
+    static final native int FT_Init_FreeType(long[] alibrary);
+    static final native int FT_Done_FreeType(long library);
+    static final native void FT_Library_Version(long library, int[] amajor, int[] aminor, int[] apatch);
+    static final native int FT_Library_SetLcdFilter(long library, int filter);
+    static final native int FT_New_Face(long library, byte[] filepathname, long face_index, long[] aface);
+    static final native int FT_Done_Face(long face);
+    static final native int FT_Get_Char_Index(long face, long charcode);
+    static final native int FT_Set_Char_Size(long face, long char_width, long char_height, int horz_resolution, int vert_resolution);
+    static final native int FT_Load_Glyph(long face, int glyph_index, int load_flags);
+    static final native void FT_Set_Transform(long face, FT_Matrix matrix, long delta_x, long delta_y);
+    static final native FT_GlyphSlotRec getGlyphSlot(long face);
+    static final native byte[] getBitmapData(long face);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/PangoFactory.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+import com.sun.javafx.font.PrismFontFactory;
+import com.sun.javafx.font.PrismFontFile;
+import com.sun.javafx.text.GlyphLayout;
+
+public class PangoFactory extends PrismFontFactory {
+
+    static boolean LCD_SUPPORT;
+
+    public static PrismFontFactory getFactory() {
+        PrismFontFactory factory = null;
+        long[] ptr = new long[1];
+        int error = OS.FT_Init_FreeType(ptr);
+        long library = ptr[0];
+        int[] major = new int[1], minor = new int[1], patch = new int[1];
+        if (error == 0) {
+            factory = new PangoFactory();
+            OS.FT_Library_Version(library, major, minor, patch);
+
+            /* This implementation only supports LDC if freetype has support. */
+            error = OS.FT_Library_SetLcdFilter(library, OS.FT_LCD_FILTER_DEFAULT);
+            LCD_SUPPORT = error == 0;
+            OS.FT_Done_FreeType(library);
+        }
+        if (PrismFontFactory.debugFonts) {
+            if (factory != null) {
+                String version = major[0] + "." + minor[0] + "." + patch[0];
+                System.err.println("Freetype2 Loaded (version " + version + ")");
+                String lcdSupport = LCD_SUPPORT ? "Enabled" : "Disabled";
+                System.err.println("LCD support " + lcdSupport);
+            } else {
+                System.err.println("Freetype2 Failed (error " + error + ")");
+            }
+        }
+        return factory;
+    }
+
+    private PangoFactory() {
+    }
+
+    @Override
+    protected PrismFontFile createFontFile(String name, String filename,
+            int fIndex, boolean register, boolean embedded, boolean copy,
+            boolean tracked) throws Exception {
+        return new FTFontFile(name, filename, fIndex, register,
+                                 embedded, copy, tracked);
+    }
+
+    @Override
+    public GlyphLayout createGlyphLayout() {
+        /* Implementing a HarfbuzzGlyphLayout would needed in order to support
+         * font features and non-hinted glyph advances.  */
+        return new PangoGlyphLayout();
+    }
+
+    @Override
+    protected boolean registerEmbeddedFont(String path) {
+        boolean result = false;
+
+        /* Test if freetype supports the file */
+        long[] ptr = new long[1];
+        int error = OS.FT_Init_FreeType(ptr);
+        if (error == 0) {
+            long library = ptr[0];
+            byte[] buffer = (path+"\0").getBytes();
+            error = OS.FT_New_Face(library, buffer, 0, ptr);
+            if (error == 0) {
+                result = true;
+                OS.FT_Done_Face(ptr[0]);
+            }
+            OS.FT_Done_FreeType(library);
+        }
+        /* Test if fontconfig supports the file  */
+        if (result) {
+            /* Adding the file to fontconfig so it can be used by pango */
+            result = OS.FcConfigAppFontAddFile(0, path);
+        }
+        if (debugFonts) {
+            if (result) {
+                System.err.println("[PANGO] Font registration succeeded:" + path);
+            } else {
+                System.err.println("[PANGO] Font registration failed:" + path);
+            }
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/PangoGlyphInfo.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+class PangoGlyphInfo {
+    int glyph;
+    /* Inline PangoGlyphGeometry */
+    int width;
+    int x_offset;
+    int y_offset;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/PangoGlyphLayout.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+import static com.sun.javafx.scene.text.TextLayout.FLAGS_ANALYSIS_VALID;
+import static com.sun.javafx.scene.text.TextLayout.FLAGS_HAS_BIDI;
+import static com.sun.javafx.scene.text.TextLayout.FLAGS_HAS_COMPLEX;
+import static com.sun.javafx.scene.text.TextLayout.FLAGS_HAS_EMBEDDED;
+import static com.sun.javafx.scene.text.TextLayout.FLAGS_HAS_TABS;
+import static com.sun.javafx.scene.text.TextLayout.FLAGS_RTL_BASE;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.StandardCharsets;
+import java.text.Bidi;
+
+import com.sun.javafx.font.CompositeFontResource;
+import com.sun.javafx.font.FontResource;
+import com.sun.javafx.font.FontStrike;
+import com.sun.javafx.font.PGFont;
+import com.sun.javafx.font.PrismFontFactory;
+import com.sun.javafx.scene.text.TextSpan;
+import com.sun.javafx.text.GlyphLayout;
+import com.sun.javafx.text.PrismTextLayout;
+import com.sun.javafx.text.ScriptMapper;
+import com.sun.javafx.text.TextRun;
+
+class PangoGlyphLayout extends GlyphLayout {
+
+    private int getSlot(PGFont font, PangoGlyphString glyphString) {
+        CompositeFontResource fr = (CompositeFontResource)font.getFontResource();
+        long fallbackFont = glyphString.font;
+        long fallbackFd = OS.pango_font_describe(fallbackFont);
+        String fallbackFamily = OS.pango_font_description_get_family(fallbackFd);
+        int fallbackStyle = OS.pango_font_description_get_style(fallbackFd);
+        int fallbackWeight = OS.pango_font_description_get_weight(fallbackFd);
+        OS.pango_font_description_free(fallbackFd);
+        boolean bold = fallbackWeight == OS.PANGO_WEIGHT_BOLD;
+        boolean italic = fallbackStyle != OS.PANGO_STYLE_NORMAL;
+
+        PrismFontFactory prismFactory = PrismFontFactory.getFontFactory();
+        PGFont fallbackPGFont = prismFactory.createFont(fallbackFamily, bold,
+                                                        italic, font.getSize());
+        String fallbackFullname =  fallbackPGFont.getFullName();
+        String primaryFullname = fr.getSlotResource(0).getFullName();
+
+        int slot = 0;
+        if (!fallbackFullname.equalsIgnoreCase(primaryFullname)) {
+            slot = fr.getSlotForFont(fallbackFullname) << 24;
+            if (PrismFontFactory.debugFonts) {
+                System.err.println("\tFallback front= "+ fallbackFullname + " slot=" + (slot>>24));
+            }
+        }
+        return slot;
+    }
+
+    private TextRun addTextRun(PrismTextLayout layout, char[] chars, int start, int length,
+                               PGFont font, TextSpan span, byte level, boolean complex) {
+
+        TextRun textRun = null;
+        if (complex) {
+            Charset utf8 = StandardCharsets.UTF_8;
+            CharsetEncoder encoder = utf8.newEncoder();
+            CharBuffer in = CharBuffer.wrap(chars, start, length);
+            int capacity = (int)(length * (double)encoder.averageBytesPerChar());
+            ByteBuffer out = ByteBuffer.allocateDirect(capacity);
+            CoderResult result = encoder.encode(in, out, true);
+            if (result.isOverflow()) {
+                capacity = (int)(length * (double)encoder.maxBytesPerChar());
+                in.rewind();
+                out = ByteBuffer.allocateDirect(capacity);
+                encoder.encode(in, out, true);
+                if (PrismFontFactory.debugFonts) {
+                    System.err.println("[PANGO] ByteBuffer capacity increased " + out);
+                }
+            }
+
+            FontResource fr = font.getFontResource();
+            boolean composite = fr instanceof CompositeFontResource;
+            if (composite) {
+                fr = ((CompositeFontResource)fr).getSlotResource(0);
+            }
+
+            long fontmap = OS.pango_ft2_font_map_new();
+            long context = OS.pango_font_map_create_context(fontmap);
+            float size = font.getSize();
+            int style = fr.isItalic() ? OS.PANGO_STYLE_ITALIC : OS.PANGO_STYLE_NORMAL;
+            int weight = fr.isBold() ? OS.PANGO_WEIGHT_BOLD : OS.PANGO_WEIGHT_NORMAL;
+            long desc = OS.pango_font_description_new();
+            OS.pango_font_description_set_family(desc, fr.getFamilyName());
+            OS.pango_font_description_set_absolute_size(desc, size * OS.PANGO_SCALE);
+            OS.pango_font_description_set_stretch(desc, OS.PANGO_STRETCH_NORMAL);
+            OS.pango_font_description_set_style(desc, style);
+            OS.pango_font_description_set_weight(desc, weight);
+            long attrList = OS.pango_attr_list_new();
+            long attr = OS.pango_attr_font_desc_new(desc);
+            OS.pango_attr_list_insert(attrList, attr);
+            if (!composite) {
+                attr = OS.pango_attr_fallback_new(false);
+                OS.pango_attr_list_insert(attrList, attr);
+            }
+            long runs = OS.pango_itemize(context, out, 0, out.position(), attrList, 0);
+            int runsCount = OS.g_list_length(runs);
+            int runStart = start;
+            for (int i = 0; i < runsCount; i++) {
+                long pangoItem = OS.g_list_nth_data(runs, i);
+                PangoGlyphString glyphString = OS.pango_shape(out, pangoItem);
+                OS.pango_item_free(pangoItem);
+                int slot = composite ? getSlot(font, glyphString) : 0;
+                int glyphCount = glyphString.num_glyphs;
+                int[] glyphs = new int[glyphCount];
+                float[] pos = new float[glyphCount*2+2];
+                PangoGlyphInfo info = null;
+                int k = 2;
+                int width = 0;
+                for (int j = 0; j < glyphCount; j++) {
+                    info = glyphString.glyphs[j];
+                    glyphs[j] = slot | info.glyph;
+                    width += info.width;
+                    pos[k] = ((float)width) / OS.PANGO_SCALE;
+                    k += 2;
+                }
+
+                int runLength = glyphString.num_chars;
+                textRun = new TextRun(runStart, runLength, level, true, 0, span, 0, false);
+                textRun.shape(glyphCount, glyphs, pos, glyphString.log_clusters);
+                layout.addTextRun(textRun);
+                runStart += runLength;
+            }
+            OS.g_list_free(runs);
+            /* pango_attr_list_unref() also frees the attributes it contains */
+            OS.pango_attr_list_unref(attrList);
+            OS.pango_font_description_free(desc);
+            OS.g_object_unref(context);
+            OS.g_object_unref(fontmap);
+        } else {
+            textRun = new TextRun(start, length, level, false, 0, span, 0, false);
+            layout.addTextRun(textRun);
+        }
+        return textRun;
+    }
+
+    public void layout(TextRun run, PGFont font, FontStrike strike, char[] text) {
+        // Nothing - complex run are analyzed by Pango during break run
+    }
+
+    public int breakRuns(PrismTextLayout layout, char[] chars, int flags) {
+        int length = chars.length;
+        boolean complexRun = false;
+        boolean complex = false;
+        boolean feature = false;
+
+        boolean checkComplex = true;
+        boolean checkBidi = true;
+        if ((flags & FLAGS_ANALYSIS_VALID) != 0) {
+            /* Avoid work when it is known neither complex
+             * text nor bidi are not present. */
+            checkComplex = (flags & FLAGS_HAS_COMPLEX) != 0;
+            checkBidi = (flags & FLAGS_HAS_BIDI) != 0;
+        }
+
+        TextRun run = null;
+        Bidi bidi = null;
+        byte bidiLevel = 0;
+        int bidiEnd = length;
+        int bidiIndex = 0;
+        int spanIndex = 0;
+        TextSpan span = null;
+        int spanEnd = length;
+        PGFont font = null;
+        TextSpan[] spans = layout.getTextSpans();
+        if (spans != null) {
+            if (spans.length > 0) {
+                span = spans[spanIndex];
+                spanEnd = span.getText().length();
+                font = (PGFont)span.getFont();
+                if (font == null) {
+                    flags |= FLAGS_HAS_EMBEDDED;
+                }
+            }
+        } else {
+            font = layout.getFont();
+        }
+        if (font != null) {
+            FontResource fr = font.getFontResource();
+            int requestedFeatures = font.getFeatures();
+            int supportedFeatures = fr.getFeatures();
+            feature = (requestedFeatures & supportedFeatures) != 0;
+        }
+        if (checkBidi && length > 0) {
+            int direction = layout.getDirection();
+            bidi = new Bidi(chars, 0, null, 0, length, direction);
+            /* Temporary Code: See RT-26997 */
+//            bidiLevel = (byte)bidi.getRunLevel(bidiIndex);
+            bidiLevel = (byte)bidi.getLevelAt(bidi.getRunStart(bidiIndex));
+            bidiEnd = bidi.getRunLimit(bidiIndex);
+            if ((bidiLevel & 1) != 0) {
+                flags |= FLAGS_HAS_BIDI;
+            }
+        }
+
+        int start = 0;
+        int i = 0;
+        while (i < length) {
+            char ch = chars[i];
+            int codePoint = ch;
+
+            boolean delimiterChanged = ch == '\t' || ch == '\n' || ch == '\r';
+            boolean spanChanged = i >= spanEnd;
+            boolean levelChanged = i >= bidiEnd;
+            boolean complexChanged = false;
+
+            if (checkComplex) {
+                if (Character.isHighSurrogate(ch)) {
+                    /* Only merge surrogate when the pair is in the same span. */
+                    if (i + 1 < spanEnd && Character.isLowSurrogate(chars[i + 1])) {
+                        codePoint = Character.toCodePoint(ch, chars[++i]);
+                    }
+                }
+                if (Character.isWhitespace(codePoint)) {
+                    complex = feature || complexRun;
+                } else {
+                    complex = feature || ScriptMapper.isComplexCharCode(codePoint);
+                }
+                complexChanged = complex != complexRun;
+            }
+
+            if (delimiterChanged || spanChanged || levelChanged || complexChanged) {
+
+                /* Create text run */
+                if (i != start) {
+                    run = addTextRun(layout, chars, start, i - start,
+                                     font, span, bidiLevel, complexRun);
+                    if (complexRun) {
+                        flags |= FLAGS_HAS_COMPLEX;
+                    }
+                    start = i;
+                }
+
+                if (delimiterChanged) {
+                    i++;
+                    /* Only merge \r\n when the are in the same text span */
+                    if (ch == '\r' && i < spanEnd && chars[i] == '\n') {
+                        i++;
+                    }
+
+                    /* Create delimiter run */
+                    run = new TextRun(start, i - start, bidiLevel, false,
+                                      ScriptMapper.COMMON, span, 0, false);
+                    if (ch == '\t') {
+                        run.setTab();
+                        flags |= FLAGS_HAS_TABS;
+                    } else {
+                        run.setLinebreak();
+                    }
+                    layout.addTextRun(run);
+
+                    start = i;
+                    if (i == length) break;
+                    spanChanged = i >= spanEnd;
+                    levelChanged = i >= bidiEnd;
+                }
+                if (spanChanged) {
+                    /* Only true for rich text (spans != null) */
+                    span = spans[++spanIndex];
+                    spanEnd += span.getText().length();
+                    font = (PGFont)span.getFont();
+                    if (font == null) {
+                        flags |= FLAGS_HAS_EMBEDDED;
+                    } else {
+                        FontResource fr = font.getFontResource();
+                        int requestedFeatures = font.getFeatures();
+                        int supportedFeatures = fr.getFeatures();
+                        feature = (requestedFeatures & supportedFeatures) != 0;
+                    }
+                }
+                if (levelChanged) {
+                    bidiIndex++;
+                    /* Temporary Code: See RT-26997 */
+//                    bidiLevel = (byte)bidi.getRunLevel(bidiIndex);
+                    bidiLevel = (byte)bidi.getLevelAt(bidi.getRunStart(bidiIndex));
+                    bidiEnd = bidi.getRunLimit(bidiIndex);
+                    if ((bidiLevel & 1) != 0) {
+                        flags |= FLAGS_HAS_BIDI;
+                    }
+                }
+
+                if (complexChanged) {
+                    if (delimiterChanged) {
+                        ch = chars[i]; /* update ch because of delimiterChanged */
+                        if (Character.isHighSurrogate(ch)) {
+                            /* Only merge surrogate when the pair is in the same span */
+                            if (i + 1 < spanEnd && Character.isLowSurrogate(chars[i + 1])) {
+                                codePoint = Character.toCodePoint(ch, chars[++i]);
+                            }
+                        }
+                        if (Character.isWhitespace(codePoint)) {
+                            complex = feature || complexRun;
+                        } else {
+                            complex = feature || ScriptMapper.isComplexCharCode(codePoint);
+                        }
+                    }
+                    complexRun = complex;
+                }
+            }
+            if (!delimiterChanged) i++;
+        }
+
+        /* Create final text run */
+        if (start < length) {
+            addTextRun(layout, chars, start, length - start,
+                       font, span, bidiLevel, complexRun);
+            if (complexRun) {
+                flags |= FLAGS_HAS_COMPLEX;
+            }
+        } else {
+            /* Ensure every lines has at least one run */
+            if (run == null || run.isLinebreak()) {
+                run = new TextRun(start, 0, (byte)0, false,
+                                  ScriptMapper.COMMON, span, 0, false);
+                layout.addTextRun(run);
+            }
+        }
+        if (bidi != null) {
+            if (!bidi.baseIsLeftToRight()) {
+                flags |= FLAGS_RTL_BASE;
+            }
+        }
+        flags |= FLAGS_ANALYSIS_VALID;
+        return flags;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/javafx/font/pango/PangoGlyphString.java	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 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.javafx.font.pango;
+
+class PangoGlyphString {
+    /* Fields from PangoItem */
+    int offset;
+    int length;
+    int num_chars;
+    /* pangoItem->analysis->font*/
+    long font;
+    int num_glyphs;
+    PangoGlyphInfo[] glyphs;
+    int[] log_clusters;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/native-font/freetype.c	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#if defined __linux__
+#if defined _ENABLE_PANGO
+
+#include <jni.h>
+#include <com_sun_javafx_font_pango_OS.h>
+#include <dlfcn.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_OUTLINE_H
+#include FT_LCD_FILTER_H
+
+#define OS_NATIVE(func) Java_com_sun_javafx_font_pango_OS_##func
+
+/**************************************************************************/
+/*                                                                        */
+/*                            Structs                                     */
+/*                                                                        */
+/**************************************************************************/
+
+typedef struct FT_Matrix_FID_CACHE {
+    int cached;
+    jfieldID xx, xy, yx, yy;
+} FT_Matrix_FID_CACHE;
+
+FT_Matrix_FID_CACHE FT_MatrixFc;
+
+void cacheFT_MatrixFields(JNIEnv *env, jobject lpObject)
+{
+    if (FT_MatrixFc.cached) return;
+    jclass clazz = (*env)->GetObjectClass(env, lpObject);
+    FT_MatrixFc.xx = (*env)->GetFieldID(env, clazz, "xx", "J");
+    FT_MatrixFc.xy = (*env)->GetFieldID(env, clazz, "xy", "J");
+    FT_MatrixFc.yx = (*env)->GetFieldID(env, clazz, "yx", "J");
+    FT_MatrixFc.yy = (*env)->GetFieldID(env, clazz, "yy", "J");
+    FT_MatrixFc.cached = 1;
+}
+
+FT_Matrix *getFT_MatrixFields(JNIEnv *env, jobject lpObject, FT_Matrix *lpStruct)
+{
+    if (!FT_MatrixFc.cached) cacheFT_MatrixFields(env, lpObject);
+    lpStruct->xx = (FT_Fixed)(*env)->GetLongField(env, lpObject, FT_MatrixFc.xx);
+    lpStruct->xy = (FT_Fixed)(*env)->GetLongField(env, lpObject, FT_MatrixFc.xy);
+    lpStruct->yx = (FT_Fixed)(*env)->GetLongField(env, lpObject, FT_MatrixFc.yx);
+    lpStruct->yy = (FT_Fixed)(*env)->GetLongField(env, lpObject, FT_MatrixFc.yy);
+    return lpStruct;
+}
+
+typedef struct FT_Bitmap_FID_CACHE {
+    int cached;
+    jfieldID rows, width, pitch, buffer, num_grays, pixel_mode, palette_mode, palette;
+} FT_Bitmap_FID_CACHE;
+
+FT_Bitmap_FID_CACHE FT_BitmapFc;
+
+void cacheFT_BitmapFields(JNIEnv *env, jobject lpObject)
+{
+    if (FT_BitmapFc.cached) return;
+    jclass clazz = (*env)->GetObjectClass(env, lpObject);
+    FT_BitmapFc.rows = (*env)->GetFieldID(env, clazz, "rows", "I");
+    FT_BitmapFc.width = (*env)->GetFieldID(env, clazz, "width", "I");
+    FT_BitmapFc.pitch = (*env)->GetFieldID(env, clazz, "pitch", "I");
+    FT_BitmapFc.buffer = (*env)->GetFieldID(env, clazz, "buffer", "J");
+    FT_BitmapFc.num_grays = (*env)->GetFieldID(env, clazz, "num_grays", "S");
+    FT_BitmapFc.pixel_mode = (*env)->GetFieldID(env, clazz, "pixel_mode", "B");
+    FT_BitmapFc.palette_mode = (*env)->GetFieldID(env, clazz, "palette_mode", "C");
+    FT_BitmapFc.palette = (*env)->GetFieldID(env, clazz, "palette", "J");
+    FT_BitmapFc.cached = 1;
+}
+
+void setFT_BitmapFields(JNIEnv *env, jobject lpObject, FT_Bitmap *lpStruct)
+{
+    if (!FT_BitmapFc.cached) cacheFT_BitmapFields(env, lpObject);
+    (*env)->SetIntField(env, lpObject, FT_BitmapFc.rows, (jint)lpStruct->rows);
+    (*env)->SetIntField(env, lpObject, FT_BitmapFc.width, (jint)lpStruct->width);
+    (*env)->SetIntField(env, lpObject, FT_BitmapFc.pitch, (jint)lpStruct->pitch);
+    (*env)->SetLongField(env, lpObject, FT_BitmapFc.buffer, (jlong)lpStruct->buffer);
+    (*env)->SetShortField(env, lpObject, FT_BitmapFc.num_grays, (jshort)lpStruct->num_grays);
+    (*env)->SetByteField(env, lpObject, FT_BitmapFc.pixel_mode, (jbyte)lpStruct->pixel_mode);
+    (*env)->SetCharField(env, lpObject, FT_BitmapFc.palette_mode, (jchar)lpStruct->palette_mode);
+    (*env)->SetLongField(env, lpObject, FT_BitmapFc.palette, (jlong)lpStruct->palette);
+}
+
+typedef struct FT_Glyph_Metrics_FID_CACHE {
+    int cached;
+    jfieldID width, height, horiBearingX, horiBearingY, horiAdvance, vertBearingX, vertBearingY, vertAdvance;
+} FT_Glyph_Metrics_FID_CACHE;
+
+FT_Glyph_Metrics_FID_CACHE FT_Glyph_MetricsFc;
+
+void cacheFT_Glyph_MetricsFields(JNIEnv *env, jobject lpObject)
+{
+    if (FT_Glyph_MetricsFc.cached) return;
+    jclass clazz = (*env)->GetObjectClass(env, lpObject);
+    FT_Glyph_MetricsFc.width = (*env)->GetFieldID(env, clazz, "width", "J");
+    FT_Glyph_MetricsFc.height = (*env)->GetFieldID(env, clazz, "height", "J");
+    FT_Glyph_MetricsFc.horiBearingX = (*env)->GetFieldID(env, clazz, "horiBearingX", "J");
+    FT_Glyph_MetricsFc.horiBearingY = (*env)->GetFieldID(env, clazz, "horiBearingY", "J");
+    FT_Glyph_MetricsFc.horiAdvance = (*env)->GetFieldID(env, clazz, "horiAdvance", "J");
+    FT_Glyph_MetricsFc.vertBearingX = (*env)->GetFieldID(env, clazz, "vertBearingX", "J");
+    FT_Glyph_MetricsFc.vertBearingY = (*env)->GetFieldID(env, clazz, "vertBearingY", "J");
+    FT_Glyph_MetricsFc.vertAdvance = (*env)->GetFieldID(env, clazz, "vertAdvance", "J");
+    FT_Glyph_MetricsFc.cached = 1;
+}
+
+void setFT_Glyph_MetricsFields(JNIEnv *env, jobject lpObject, FT_Glyph_Metrics *lpStruct)
+{
+    if (!FT_Glyph_MetricsFc.cached) cacheFT_Glyph_MetricsFields(env, lpObject);
+    (*env)->SetLongField(env, lpObject, FT_Glyph_MetricsFc.width, (jlong)lpStruct->width);
+    (*env)->SetLongField(env, lpObject, FT_Glyph_MetricsFc.height, (jlong)lpStruct->height);
+    (*env)->SetLongField(env, lpObject, FT_Glyph_MetricsFc.horiBearingX, (jlong)lpStruct->horiBearingX);
+    (*env)->SetLongField(env, lpObject, FT_Glyph_MetricsFc.horiBearingY, (jlong)lpStruct->horiBearingY);
+    (*env)->SetLongField(env, lpObject, FT_Glyph_MetricsFc.horiAdvance, (jlong)lpStruct->horiAdvance);
+    (*env)->SetLongField(env, lpObject, FT_Glyph_MetricsFc.vertBearingX, (jlong)lpStruct->vertBearingX);
+    (*env)->SetLongField(env, lpObject, FT_Glyph_MetricsFc.vertBearingY, (jlong)lpStruct->vertBearingY);
+    (*env)->SetLongField(env, lpObject, FT_Glyph_MetricsFc.vertAdvance, (jlong)lpStruct->vertAdvance);
+}
+
+typedef struct FT_GlyphSlotRec_FID_CACHE {
+    int cached;
+    jclass clazz;
+    jfieldID metrics, linearHoriAdvance, linearVertAdvance, advance_x, advance_y, format, bitmap, bitmap_left, bitmap_top;
+    jmethodID init;
+} FT_GlyphSlotRec_FID_CACHE;
+
+FT_GlyphSlotRec_FID_CACHE FT_GlyphSlotRecFc;
+
+void cacheFT_GlyphSlotRecFields(JNIEnv *env)
+{
+    if (FT_GlyphSlotRecFc.cached) return;
+    jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/font/pango/FT_GlyphSlotRec");
+    FT_GlyphSlotRecFc.clazz =  (jclass)(*env)->NewGlobalRef(env, tmpClass);
+    FT_GlyphSlotRecFc.metrics = (*env)->GetFieldID(env, FT_GlyphSlotRecFc.clazz, "metrics", "Lcom/sun/javafx/font/pango/FT_Glyph_Metrics;");
+    FT_GlyphSlotRecFc.linearHoriAdvance = (*env)->GetFieldID(env, FT_GlyphSlotRecFc.clazz, "linearHoriAdvance", "J");
+    FT_GlyphSlotRecFc.linearVertAdvance = (*env)->GetFieldID(env, FT_GlyphSlotRecFc.clazz, "linearVertAdvance", "J");
+    FT_GlyphSlotRecFc.advance_x = (*env)->GetFieldID(env, FT_GlyphSlotRecFc.clazz, "advance_x", "J");
+    FT_GlyphSlotRecFc.advance_y = (*env)->GetFieldID(env, FT_GlyphSlotRecFc.clazz, "advance_y", "J");
+    FT_GlyphSlotRecFc.format = (*env)->GetFieldID(env, FT_GlyphSlotRecFc.clazz, "format", "I");
+    FT_GlyphSlotRecFc.bitmap = (*env)->GetFieldID(env, FT_GlyphSlotRecFc.clazz, "bitmap", "Lcom/sun/javafx/font/pango/FT_Bitmap;");
+    FT_GlyphSlotRecFc.bitmap_left = (*env)->GetFieldID(env, FT_GlyphSlotRecFc.clazz, "bitmap_left", "I");
+    FT_GlyphSlotRecFc.bitmap_top = (*env)->GetFieldID(env, FT_GlyphSlotRecFc.clazz, "bitmap_top", "I");
+    FT_GlyphSlotRecFc.init = (*env)->GetMethodID(env, FT_GlyphSlotRecFc.clazz, "<init>", "()V");
+    FT_GlyphSlotRecFc.cached = 1;
+}
+
+void setFT_GlyphSlotRecFields(JNIEnv *env, jobject lpObject, FT_GlyphSlotRec *lpStruct)
+{
+    if (!FT_GlyphSlotRecFc.cached) cacheFT_GlyphSlotRecFields(env);
+    {
+    jobject lpObject1 = (*env)->GetObjectField(env, lpObject, FT_GlyphSlotRecFc.metrics);
+    if (lpObject1 != NULL) setFT_Glyph_MetricsFields(env, lpObject1, &lpStruct->metrics);
+    }
+    (*env)->SetLongField(env, lpObject, FT_GlyphSlotRecFc.linearHoriAdvance, (jlong)lpStruct->linearHoriAdvance);
+    (*env)->SetLongField(env, lpObject, FT_GlyphSlotRecFc.linearVertAdvance, (jlong)lpStruct->linearVertAdvance);
+    (*env)->SetLongField(env, lpObject, FT_GlyphSlotRecFc.advance_x, (jlong)lpStruct->advance.x);
+    (*env)->SetLongField(env, lpObject, FT_GlyphSlotRecFc.advance_y, (jlong)lpStruct->advance.y);
+    (*env)->SetIntField(env, lpObject, FT_GlyphSlotRecFc.format, (jint)lpStruct->format);
+    {
+    jobject lpObject1 = (*env)->GetObjectField(env, lpObject, FT_GlyphSlotRecFc.bitmap);
+    if (lpObject1 != NULL) setFT_BitmapFields(env, lpObject1, &lpStruct->bitmap);
+    }
+    (*env)->SetIntField(env, lpObject, FT_GlyphSlotRecFc.bitmap_left, (jint)lpStruct->bitmap_left);
+    (*env)->SetIntField(env, lpObject, FT_GlyphSlotRecFc.bitmap_top, (jint)lpStruct->bitmap_top);
+}
+
+jobject newFT_GlyphSlotRec(JNIEnv *env, FT_GlyphSlotRec *lpStruct)
+{
+    jobject lpObject = NULL;
+    if (!FT_GlyphSlotRecFc.cached) cacheFT_GlyphSlotRecFields(env);
+    lpObject = (*env)->NewObject(env, FT_GlyphSlotRecFc.clazz, FT_GlyphSlotRecFc.init);
+    if (lpObject && lpStruct) setFT_GlyphSlotRecFields(env, lpObject, lpStruct);
+    return lpObject;
+}
+
+/**************************************************************************/
+/*                                                                        */
+/*                           Functions                                    */
+/*                                                                        */
+/**************************************************************************/
+
+JNIEXPORT jobject JNICALL OS_NATIVE(getGlyphSlot)(JNIEnv *env, jclass that, jlong facePtr)
+{
+    jobject result = NULL;
+    if (facePtr) {
+        FT_Face face = (FT_Face)facePtr;
+        FT_GlyphSlot slot = face->glyph;
+        if (slot) {
+            result = newFT_GlyphSlotRec(env, slot);
+        }
+    }
+    return result;
+}
+
+JNIEXPORT jbyteArray JNICALL OS_NATIVE(getBitmapData)(JNIEnv *env, jclass that, jlong facePtr)
+{
+    if (!facePtr) return NULL;
+    FT_Face face = (FT_Face)facePtr;
+    FT_GlyphSlot slot = face->glyph;
+    if (!slot) return NULL;
+    FT_Bitmap bitmap = slot->bitmap;
+    unsigned char* src = bitmap.buffer;
+    if (!src) return NULL;
+    size_t size = bitmap.pitch * bitmap.rows;
+    jbyteArray result = (*env)->NewByteArray(env, size);
+    if (result) {
+        unsigned char* dst = (*env)->GetPrimitiveArrayCritical(env, result, NULL);
+        if (dst) {
+            memcpy(dst, src, size);
+            (*env)->ReleasePrimitiveArrayCritical(env, result, dst, 0);
+        }
+    }
+    return result;
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(FT_1Set_1Transform)
+    (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jlong arg2, jlong arg3)
+{
+    FT_Vector *lpDelta = NULL;
+    if (arg2 || arg3) {
+        FT_Vector vec = {arg2, arg3};
+        lpDelta = &vec;
+    }
+    if (arg1) {
+        FT_Matrix matrix, *lpMatrix = NULL;
+        lpMatrix = getFT_MatrixFields(env, arg1, &matrix);
+        if (lpMatrix) {
+            FT_Set_Transform((FT_Face)arg0, lpMatrix, lpDelta);
+        }
+    }
+}
+
+#define LIB_FREETYPE "libfreetype.so"
+JNIEXPORT jint JNICALL OS_NATIVE(FT_1Library_1SetLcdFilter)
+    (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+//  return (jint)FT_Library_SetLcdFilter((FT_Library)arg0, (FT_LcdFilter)arg1);
+    static void *fp = NULL;
+    if (!fp) {
+        void* handle = dlopen(LIB_FREETYPE, RTLD_LAZY);
+        if (handle) fp = dlsym(handle, "FT_Library_SetLcdFilter");
+    }
+    jint rc = 0;
+    if (fp) {
+        rc = (jint)((jint (*)(jlong, jint))fp)(arg0, arg1);
+    }
+    return rc;
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(FT_1Done_1Face)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    return (jint)FT_Done_Face((FT_Face)arg0);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(FT_1Library_1Version)
+    (JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jintArray arg2, jintArray arg3)
+{
+    jint *lparg1=NULL;
+    jint *lparg2=NULL;
+    jint *lparg3=NULL;
+    if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail;
+    if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
+    if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+    FT_Library_Version((FT_Library)arg0, lparg1, lparg2, lparg3);
+fail:
+    if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+    if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
+    if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0);
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(FT_1Done_1FreeType)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    return (jint)FT_Done_FreeType((FT_Library)arg0);
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(FT_1Init_1FreeType)
+    (JNIEnv *env, jclass that, jlongArray arg0)
+{
+    jlong *lparg0=NULL;
+    jint rc = 0;
+    if (arg0) if ((lparg0 = (*env)->GetLongArrayElements(env, arg0, NULL)) == NULL) goto fail;
+    rc = (jint)FT_Init_FreeType((FT_Library  *)lparg0);
+fail:
+    if (arg0 && lparg0) (*env)->ReleaseLongArrayElements(env, arg0, lparg0, 0);
+    return rc;
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(FT_1Load_1Glyph)
+    (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
+{
+    return (jint)FT_Load_Glyph((FT_Face)arg0, (FT_UInt)arg1, (FT_Int32)arg2);
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(FT_1New_1Face)
+    (JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1, jlong arg2, jlongArray arg3)
+{
+    jbyte *lparg1=NULL;
+    jlong *lparg3=NULL;
+    jint rc = 0;
+    if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail;
+    if (arg3) if ((lparg3 = (*env)->GetLongArrayElements(env, arg3, NULL)) == NULL) goto fail;
+    rc = (jint)FT_New_Face((FT_Library)arg0, (const char*)lparg1, (FT_Long)arg2, (FT_Face  *)lparg3);
+fail:
+    if (arg3 && lparg3) (*env)->ReleaseLongArrayElements(env, arg3, lparg3, 0);
+    if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0);
+    return rc;
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(FT_1Set_1Char_1Size)
+    (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jlong arg2, jint arg3, jint arg4)
+{
+    return (jint)FT_Set_Char_Size((FT_Face)arg0, (FT_F26Dot6)arg1, (FT_F26Dot6)arg2, (FT_UInt)arg3, (FT_UInt)arg4);
+}
+
+/***********************************************/
+/*                Glyph Outline                */
+/***********************************************/
+
+#define F26DOT6TOFLOAT(n) (float)n/64.0;
+static const int DEFAULT_LEN_TYPES = 10;
+static const int DEFAULT_LEN_COORDS = 50;
+typedef struct _PathData {
+    jbyte* pointTypes;
+    int numTypes;
+    int lenTypes;
+    jfloat* pointCoords;
+    int numCoords;
+    int lenCoords;
+} PathData;
+
+static PathData* checkSize(void* user, int coordCount)
+{
+    PathData* info = (PathData *)user;
+    if (info->numTypes == info->lenTypes) {
+        info->lenTypes += DEFAULT_LEN_TYPES;
+        info->pointTypes = (jbyte*)realloc(info->pointTypes, info->lenTypes * sizeof(jbyte));
+    }
+    if (info->numCoords + (coordCount * 2) > info->lenCoords) {
+        info->lenCoords += DEFAULT_LEN_COORDS;
+        info->pointCoords = (jfloat*)realloc(info->pointCoords, info->lenCoords * sizeof(jfloat));
+    }
+    return info;
+}
+
+static int JFX_Outline_MoveToFunc(const FT_Vector*   to,
+                                  void*              user)
+{
+    PathData *info = checkSize(user, 1);
+    info->pointTypes[info->numTypes++] = 0;
+    info->pointCoords[info->numCoords++] = F26DOT6TOFLOAT(to->x);
+    info->pointCoords[info->numCoords++] = -F26DOT6TOFLOAT(to->y);
+    return 0;
+}
+
+static int JFX_Outline_LineToFunc(const FT_Vector*   to,
+                                  void* user)
+{
+    PathData *info =  checkSize(user, 1);
+    info->pointTypes[info->numTypes++] = 1;
+    info->pointCoords[info->numCoords++] = F26DOT6TOFLOAT(to->x);
+    info->pointCoords[info->numCoords++] = -F26DOT6TOFLOAT(to->y);
+    return 0;
+}
+
+static int JFX_Outline_ConicToFunc(const FT_Vector*  control,
+                                   const FT_Vector*  to,
+                                   void*             user )
+{
+    PathData *info = checkSize(user, 2);
+    info->pointTypes[info->numTypes++] = 2;
+    info->pointCoords[info->numCoords++] = F26DOT6TOFLOAT(control->x);
+    info->pointCoords[info->numCoords++] = -F26DOT6TOFLOAT(control->y);
+    info->pointCoords[info->numCoords++] = F26DOT6TOFLOAT(to->x);
+    info->pointCoords[info->numCoords++] = -F26DOT6TOFLOAT(to->y);
+    return 0;
+}
+
+static int JFX_Outline_CubicToFunc(const FT_Vector*  control1,
+                                   const FT_Vector*  control2,
+                                   const FT_Vector*  to,
+                                   void*             user)
+{
+    PathData *info = checkSize(user, 3);
+    info->pointTypes[info->numTypes++] = 3;
+    info->pointCoords[info->numCoords++] = F26DOT6TOFLOAT(control1->x);
+    info->pointCoords[info->numCoords++] = -F26DOT6TOFLOAT(control1->y);
+    info->pointCoords[info->numCoords++] = F26DOT6TOFLOAT(control2->x);
+    info->pointCoords[info->numCoords++] = -F26DOT6TOFLOAT(control2->y);
+    info->pointCoords[info->numCoords++] = F26DOT6TOFLOAT(to->x);
+    info->pointCoords[info->numCoords++] = -F26DOT6TOFLOAT(to->y);
+    return 0;
+}
+
+static const  FT_Outline_Funcs JFX_Outline_Funcs =
+{
+    JFX_Outline_MoveToFunc,
+    JFX_Outline_LineToFunc,
+    JFX_Outline_ConicToFunc,
+    JFX_Outline_CubicToFunc,
+    0, 0
+};
+
+JNIEXPORT jobject JNICALL OS_NATIVE(FT_1Outline_1Decompose)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    FT_Face face = (FT_Face)arg0;
+    if (face == NULL) return NULL;
+    FT_GlyphSlot slot = face->glyph;
+    if (slot == NULL) return NULL;
+    FT_Outline* outline = &slot->outline;
+    if (outline == NULL) return NULL;
+
+    jobject path2D = NULL;
+    PathData data;
+    data.pointTypes = (jbyte*)malloc(sizeof(jbyte) * DEFAULT_LEN_TYPES);
+    data.numTypes = 0;
+    data.lenTypes = DEFAULT_LEN_TYPES;
+    data.pointCoords = (jfloat*)malloc(sizeof(jfloat) * DEFAULT_LEN_COORDS);
+    data.numCoords = 0;
+    data.lenCoords = DEFAULT_LEN_COORDS;
+
+    /* Decompose outline */
+    FT_Outline_Decompose(outline, &JFX_Outline_Funcs, &data);
+
+    static jclass path2DClass = NULL;
+    static jmethodID path2DCtr = NULL;
+    if (path2DClass == NULL) {
+        jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/geom/Path2D");
+        path2DClass = (jclass)(*env)->NewGlobalRef(env, tmpClass);
+        path2DCtr = (*env)->GetMethodID(env, path2DClass, "<init>", "(I[BI[FI)V");
+    }
+
+    jbyteArray types = (*env)->NewByteArray(env, data.numTypes);
+    jfloatArray coords = (*env)->NewFloatArray(env, data.numCoords);
+    if (types && coords) {
+        (*env)->SetByteArrayRegion(env, types, 0, data.numTypes, data.pointTypes);
+        (*env)->SetFloatArrayRegion(env, coords, 0, data.numCoords, data.pointCoords);
+        path2D = (*env)->NewObject(env, path2DClass, path2DCtr,
+                                   0 /*winding rule*/,
+                                   types, data.numTypes,
+                                   coords, data.numCoords);
+    }
+    free(data.pointTypes);
+    free(data.pointCoords);
+    return path2D;
+}
+
+#endif /* ENABLE_PANGO */
+#endif /* __linux__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/native-font/pango.c	Fri Jul 05 10:54:43 2013 -0700
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#if defined __linux__
+#if defined _ENABLE_PANGO
+
+#include <jni.h>
+#include <com_sun_javafx_font_pango_OS.h>
+#include <pango/pango.h>
+#include <pango/pangoft2.h>
+#include <dlfcn.h>
+
+#define OS_NATIVE(func) Java_com_sun_javafx_font_pango_OS_##func
+
+/**************************************************************************/
+/*                                                                        */
+/*                            Structs                                     */
+/*                                                                        */
+/**************************************************************************/
+
+typedef struct PangoGlyphInfo_FID_CACHE {
+    int cached;
+    jclass clazz;
+    jfieldID glyph, width, x_offset, y_offset;
+    jmethodID init;
+} PangoGlyphInfo_FID_CACHE;
+
+PangoGlyphInfo_FID_CACHE PangoGlyphInfoFc;
+
+void cachePangoGlyphInfoFields(JNIEnv *env)
+{
+    if (PangoGlyphInfoFc.cached) return;
+    jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/font/pango/PangoGlyphInfo");
+    PangoGlyphInfoFc.clazz =  (jclass)(*env)->NewGlobalRef(env, tmpClass);
+    PangoGlyphInfoFc.glyph = (*env)->GetFieldID(env, PangoGlyphInfoFc.clazz, "glyph", "I");
+    PangoGlyphInfoFc.width = (*env)->GetFieldID(env, PangoGlyphInfoFc.clazz, "width", "I");
+    PangoGlyphInfoFc.x_offset = (*env)->GetFieldID(env, PangoGlyphInfoFc.clazz, "x_offset", "I");
+    PangoGlyphInfoFc.y_offset = (*env)->GetFieldID(env, PangoGlyphInfoFc.clazz, "y_offset", "I");
+    PangoGlyphInfoFc.init = (*env)->GetMethodID(env, PangoGlyphInfoFc.clazz, "<init>", "()V");
+    PangoGlyphInfoFc.cached = 1;
+}
+
+void setPangoGlyphInfoFields(JNIEnv *env, jobject lpObject, PangoGlyphInfo *lpStruct)
+{
+    if (!PangoGlyphInfoFc.cached) cachePangoGlyphInfoFields(env);
+    (*env)->SetIntField(env, lpObject, PangoGlyphInfoFc.glyph, (jint)lpStruct->glyph);
+    (*env)->SetIntField(env, lpObject, PangoGlyphInfoFc.width, (jint)lpStruct->geometry.width);
+    (*env)->SetIntField(env, lpObject, PangoGlyphInfoFc.x_offset, (jint)lpStruct->geometry.x_offset);
+    (*env)->SetIntField(env, lpObject, PangoGlyphInfoFc.y_offset, (jint)lpStruct->geometry.y_offset);
+}
+
+jobject newPangoGlyphInfo(JNIEnv *env, PangoGlyphInfo *lpStruct)
+{
+    jobject lpObject = NULL;
+    if (!PangoGlyphInfoFc.cached) cachePangoGlyphInfoFields(env);
+    lpObject = (*env)->NewObject(env, PangoGlyphInfoFc.clazz, PangoGlyphInfoFc.init);
+    if (lpObject && lpStruct) setPangoGlyphInfoFields(env, lpObject, lpStruct);
+    return lpObject;
+}
+
+typedef struct PangoGlyphString_FID_CACHE {
+    int cached;
+    jclass clazz;
+    jfieldID num_glyphs, glyphs, log_clusters, offset, length, num_chars, font;
+    jmethodID init;
+} PangoGlyphString_FID_CACHE;
+
+PangoGlyphString_FID_CACHE PangoGlyphStringFc;
+
+void cachePangoGlyphStringFields(JNIEnv *env)
+{
+    if (PangoGlyphStringFc.cached) return;
+    jclass tmpClass = (*env)->FindClass(env, "com/sun/javafx/font/pango/PangoGlyphString");
+    PangoGlyphStringFc.clazz =  (jclass)(*env)->NewGlobalRef(env, tmpClass);
+    PangoGlyphStringFc.num_glyphs = (*env)->GetFieldID(env, PangoGlyphStringFc.clazz, "num_glyphs", "I");
+    PangoGlyphStringFc.glyphs = (*env)->GetFieldID(env, PangoGlyphStringFc.clazz, "glyphs", "[Lcom/sun/javafx/font/pango/PangoGlyphInfo;");
+    PangoGlyphStringFc.log_clusters = (*env)->GetFieldID(env, PangoGlyphStringFc.clazz, "log_clusters", "[I");
+    PangoGlyphStringFc.offset = (*env)->GetFieldID(env, PangoGlyphStringFc.clazz, "offset", "I");
+    PangoGlyphStringFc.length = (*env)->GetFieldID(env, PangoGlyphStringFc.clazz, "length", "I");
+    PangoGlyphStringFc.num_chars = (*env)->GetFieldID(env, PangoGlyphStringFc.clazz, "num_chars", "I");
+    PangoGlyphStringFc.font = (*env)->GetFieldID(env, PangoGlyphStringFc.clazz, "font", "J");
+    PangoGlyphStringFc.init = (*env)->GetMethodID(env, PangoGlyphStringFc.clazz, "<init>", "()V");
+    PangoGlyphStringFc.cached = 1;
+}
+
+/**************************************************************************/
+/*                                                                        */
+/*                           Functions                                    */
+/*                                                                        */
+/**************************************************************************/
+
+/** Custom **/
+JNIEXPORT jlong JNICALL OS_NATIVE(pango_1itemize)
+    (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2, jint arg3, jlong arg4, jlong arg5)
+{
+    jbyte *lparg1=NULL;
+    jlong rc = 0;
+    if (arg1) lparg1 = (*env)->GetDirectBufferAddress(env, arg1);
+    if (lparg1) {
+        rc = (jlong)pango_itemize((PangoContext *)arg0, (const char *)lparg1, arg2, arg3, (PangoAttrList *)arg4, (PangoAttrIterator *)arg5);
+    }
+    return rc;
+}
+
+
+JNIEXPORT jobject JNICALL OS_NATIVE(pango_1shape)
+    (JNIEnv *env, jclass that, jobject nioBuffer, jlong pangoItem)
+{
+    if (!pangoItem) return NULL;
+    if (!nioBuffer) return NULL;
+    void *bytePtr = (*env)->GetDirectBufferAddress(env, nioBuffer);
+    if (!bytePtr) return NULL;
+    PangoItem *item = (PangoItem *)pangoItem;
+    PangoAnalysis analysis = item->analysis;
+    const gchar *text= bytePtr + item->offset;
+    PangoGlyphString *glyphs = pango_glyph_string_new();
+
+    pango_shape(text, item->length, &analysis, glyphs);
+    int count = glyphs->num_glyphs;
+    if(count == 0) return NULL;
+
+    if (!PangoGlyphInfoFc.cached) cachePangoGlyphInfoFields(env);
+    jobjectArray infoArray = (*env)->NewObjectArray(env, count, PangoGlyphInfoFc.clazz, NULL);
+    jintArray clusterArray = (*env)->NewIntArray(env, count);
+    jobject result = NULL;
+    if (infoArray && clusterArray) {
+        jint cluster[count];
+        int i;
+        for (i = 0; i < count; i++) {
+            jobject info = newPangoGlyphInfo(env, &glyphs->glyphs[i]);
+            (*env)->SetObjectArrayElement(env, infoArray, i, info);
+            /* translate byte index to char index */
+            cluster[i] = (jint)g_utf8_pointer_to_offset(text, text + glyphs->log_clusters[i]);
+        }
+        (*env)->SetIntArrayRegion(env, clusterArray, 0, count, cluster);
+        if (!PangoGlyphStringFc.cached) cachePangoGlyphStringFields(env);
+        result = (*env)->NewObject(env, PangoGlyphStringFc.clazz, PangoGlyphStringFc.init);
+        if (result) {
+            (*env)->SetIntField(env, result, PangoGlyphStringFc.num_glyphs, count);
+
+            /* Set custom fields */
+            (*env)->SetObjectField(env, result, PangoGlyphStringFc.glyphs, infoArray);
+            (*env)->SetObjectField(env, result, PangoGlyphStringFc.log_clusters, clusterArray);
+            (*env)->SetIntField(env, result, PangoGlyphStringFc.offset, item->offset);
+            (*env)->SetIntField(env, result, PangoGlyphStringFc.length, item->length);
+            (*env)->SetIntField(env, result, PangoGlyphStringFc.num_chars, item->num_chars);
+            (*env)->SetLongField(env, result, PangoGlyphStringFc.font, (jlong)analysis.font);
+        }
+    }
+    pango_glyph_string_free(glyphs);
+    return result;
+}
+
+JNIEXPORT jstring JNICALL OS_NATIVE(pango_1font_1description_1get_1family)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    const char *family = pango_font_description_get_family((PangoFontDescription *)arg0);
+    return (*env)->NewStringUTF(env, family);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(pango_1font_1description_1set_1family)
+    (JNIEnv *env, jclass that, jlong arg0, jstring arg1)
+{
+    if (arg1) {
+        const char *text = (*env)->GetStringUTFChars(env, arg1, NULL);
+        if (text) {
+            pango_font_description_set_family((PangoFontDescription *)arg0, text);
+            (*env)->ReleaseStringUTFChars(env, arg1, text);
+        }
+    }
+}
+
+#define LIB_FONTCONFIG "libfontconfig.so.1"
+JNIEXPORT jboolean JNICALL OS_NATIVE(FcConfigAppFontAddFile)
+    (JNIEnv *env, jclass that, jlong arg0, jstring arg1)
+{
+    static void *fp = NULL;
+    if (!fp) {
+        void* handle = dlopen(LIB_FONTCONFIG, RTLD_LAZY);
+        if (handle) fp = dlsym(handle, "FcConfigAppFontAddFile");
+    }
+    jboolean rc = 0;
+    if (arg1) {
+        const char *text = (*env)->GetStringUTFChars(env, arg1, NULL);
+        if (text) {
+//            rc = (jboolean)FcConfigAppFontAddFile(arg0, text);
+            if (fp) {
+                rc = (jboolean)((jboolean (*)(jlong, const char *))fp)(arg0, text);
+            }
+            (*env)->ReleaseStringUTFChars(env, arg1, text);
+        }
+    }
+    return rc;
+}
+
+/** one to one **/
+JNIEXPORT jlong JNICALL OS_NATIVE(pango_1font_1describe)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    return (jlong)pango_font_describe((PangoFont *)arg0);
+}
+
+JNIEXPORT jlong JNICALL OS_NATIVE(pango_1attr_1fallback_1new)
+    (JNIEnv *env, jclass that, jboolean arg0)
+{
+    return (jlong)pango_attr_fallback_new(arg0);
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(pango_1font_1description_1get_1stretch)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    return (jint)pango_font_description_get_stretch((PangoFontDescription *)arg0);
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(pango_1font_1description_1get_1style)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    return (jint)pango_font_description_get_style((PangoFontDescription *)arg0);
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(pango_1font_1description_1get_1weight)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    return (jint)pango_font_description_get_weight((PangoFontDescription *)arg0);
+}
+
+JNIEXPORT jlong JNICALL OS_NATIVE(pango_1ft2_1font_1map_1new)
+    (JNIEnv *env, jclass that)
+{
+    return (jlong)pango_ft2_font_map_new();
+}
+
+JNIEXPORT jlong JNICALL OS_NATIVE(pango_1font_1map_1create_1context)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    return (jlong)pango_font_map_create_context((PangoFontMap *)arg0);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(g_1object_1unref)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    g_object_unref((gpointer)arg0);
+}
+
+JNIEXPORT jlong JNICALL OS_NATIVE(pango_1font_1description_1new)
+    (JNIEnv *env, jclass that)
+{
+    return (jlong)pango_font_description_new();
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(pango_1font_1description_1set_1absolute_1size)
+    (JNIEnv *env, jclass that, jlong arg0, jdouble arg1)
+{
+    pango_font_description_set_absolute_size((PangoFontDescription *)arg0, arg1);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(pango_1font_1description_1set_1stretch)
+    (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+    pango_font_description_set_stretch((PangoFontDescription *)arg0, (PangoStretch)arg1);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(pango_1font_1description_1set_1style)
+    (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+    pango_font_description_set_style((PangoFontDescription *)arg0, (PangoStyle)arg1);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(pango_1font_1description_1set_1weight)
+    (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+    pango_font_description_set_weight((PangoFontDescription *)arg0, (PangoWeight)arg1);
+}
+
+JNIEXPORT jlong JNICALL OS_NATIVE(pango_1attr_1list_1new)
+    (JNIEnv *env, jclass that)
+{
+    return (jlong)pango_attr_list_new();
+}
+
+JNIEXPORT jlong JNICALL OS_NATIVE(pango_1attr_1font_1desc_1new)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    return (jlong)pango_attr_font_desc_new((const PangoFontDescription *)arg0);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(pango_1attr_1list_1insert)
+    (JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+    pango_attr_list_insert((PangoAttrList *)arg0, (PangoAttribute *)arg1);
+}
+
+JNIEXPORT jint JNICALL OS_NATIVE(g_1list_1length)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    return (jint)g_list_length((GList *)arg0);
+}
+
+JNIEXPORT jlong JNICALL OS_NATIVE(g_1list_1nth_1data)
+    (JNIEnv *env, jclass that, jlong arg0, jint arg1)
+{
+    return (jlong)g_list_nth_data((GList *)arg0, (guint)arg1);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(pango_1item_1free)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    pango_item_free((PangoItem *)arg0);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(g_1list_1free)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    g_list_free((GList *)arg0);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(pango_1attr_1list_1unref)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    pango_attr_list_unref((PangoAttrList *)arg0);
+}
+
+JNIEXPORT void JNICALL OS_NATIVE(pango_1font_1description_1free)
+    (JNIEnv *env, jclass that, jlong arg0)
+{
+    pango_font_description_free((PangoFontDescription *)arg0);
+}
+
+#endif /* ENABLE_PANGO */
+#endif /* __linux__ */