/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.glview.freetype;
import java.nio.ByteBuffer;
import android.util.Log;
import com.glview.Lib;
public class FreeType {
// @off
/*JNI
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_STROKER_H
*/
private static class Pointer {
long address;
Pointer(long address) {
this.address = address;
}
public long address() {
return address;
}
}
public static class Library extends Pointer {
Library (long address) {
super(address);
}
public void dispose () {
doneFreeType(address);
}
private static native void doneFreeType(long library); /*
FT_Done_FreeType((FT_Library)library);
*/
public Face newMemoryFace(byte[] data, int dataSize, int faceIndex) {
ByteBuffer buffer = ByteBuffer.allocateDirect(data.length);
buffer.put(data, 0, data.length);
buffer.position(0);
return newMemoryFace(buffer, faceIndex);
}
public Face newMemoryFace(ByteBuffer buffer, int faceIndex) {
long face = newMemoryFace(address, buffer, buffer.remaining(), faceIndex);
if(face == 0) {
throw new RuntimeException("Couldn't load font");
}
else {
return new Face(face, this, buffer);
}
}
private static native long newMemoryFace(long library, ByteBuffer data, int dataSize, int faceIndex); /*
FT_Face face = 0;
FT_Error error = FT_New_Memory_Face((FT_Library)library, (const FT_Byte*)data, dataSize, faceIndex, &face);
if(error) return 0;
else return (jlong)face;
*/
public Stroker createStroker() {
long stroker = strokerNew(address);
if(stroker == 0) throw new RuntimeException("Couldn't create FreeType stroker");
return new Stroker(stroker);
}
private static native long strokerNew(long library); /*
FT_Stroker stroker;
FT_Error error = FT_Stroker_New((FT_Library)library, &stroker);
if(error) return 0;
else return (jlong)stroker;
*/
}
public static class Face extends Pointer {
Library library;
public final ByteBuffer buffer;
public Face (long address, Library library, ByteBuffer buffer) {
super(address);
this.library = library;
this.buffer = buffer;
}
public void dispose() {
doneFace(address);
}
private static native void doneFace(long face); /*
FT_Done_Face((FT_Face)face);
*/
public int getFaceFlags() {
return getFaceFlags(address);
}
private static native int getFaceFlags(long face); /*
return ((FT_Face)face)->face_flags;
*/
public int getStyleFlags() {
return getStyleFlags(address);
}
private static native int getStyleFlags(long face); /*
return ((FT_Face)face)->style_flags;
*/
public int getNumGlyphs() {
return getNumGlyphs(address);
}
private static native int getNumGlyphs(long face); /*
return ((FT_Face)face)->num_glyphs;
*/
public int getAscender() {
return getAscender(address);
}
private static native int getAscender(long face); /*
return ((FT_Face)face)->ascender;
*/
public int getDescender() {
return getDescender(address);
}
private static native int getDescender(long face); /*
return ((FT_Face)face)->descender;
*/
public int getHeight() {
return getHeight(address);
}
private static native int getHeight(long face); /*
return ((FT_Face)face)->height;
*/
public int getMaxAdvanceWidth() {
return getMaxAdvanceWidth(address);
}
private static native int getMaxAdvanceWidth(long face); /*
return ((FT_Face)face)->max_advance_width;
*/
public int getMaxAdvanceHeight() {
return getMaxAdvanceHeight(address);
}
private static native int getMaxAdvanceHeight(long face); /*
return ((FT_Face)face)->max_advance_height;
*/
public int getUnderlinePosition() {
return getUnderlinePosition(address);
}
private static native int getUnderlinePosition(long face); /*
return ((FT_Face)face)->underline_position;
*/
public int getUnderlineThickness() {
return getUnderlineThickness(address);
}
private static native int getUnderlineThickness(long face); /*
return ((FT_Face)face)->underline_thickness;
*/
public boolean selectSize(int strikeIndex) {
return selectSize(address, strikeIndex);
}
private static native boolean selectSize(long face, int strike_index); /*
return !FT_Select_Size((FT_Face)face, strike_index);
*/
public boolean setCharSize(int charWidth, int charHeight, int horzResolution, int vertResolution) {
return setCharSize(address, charWidth, charHeight, horzResolution, vertResolution);
}
private static native boolean setCharSize(long face, int charWidth, int charHeight, int horzResolution, int vertResolution); /*
return !FT_Set_Char_Size((FT_Face)face, charWidth, charHeight, horzResolution, vertResolution);
*/
public boolean setPixelSizes(int pixelWidth, int pixelHeight) {
return setPixelSizes(address, pixelWidth, pixelHeight);
}
private static native boolean setPixelSizes(long face, int pixelWidth, int pixelHeight); /*
return !FT_Set_Pixel_Sizes((FT_Face)face, pixelWidth, pixelHeight);
*/
public boolean loadGlyph(int glyphIndex, int loadFlags) {
return loadGlyph(address, glyphIndex, loadFlags);
}
private static native boolean loadGlyph(long face, int glyphIndex, int loadFlags); /*
return !FT_Load_Glyph((FT_Face)face, glyphIndex, loadFlags);
*/
public boolean loadChar(int charCode, int loadFlags) {
return loadChar(address, charCode, loadFlags);
}
private static native boolean loadChar(long face, int charCode, int loadFlags); /*
return !FT_Load_Char((FT_Face)face, charCode, loadFlags);
*/
public GlyphSlot getGlyph() {
return new GlyphSlot(getGlyph(address));
}
private static native long getGlyph(long face); /*
return (jlong)((FT_Face)face)->glyph;
*/
public Size getSize() {
return new Size(getSize(address));
}
private static native long getSize(long face); /*
return (jlong)((FT_Face)face)->size;
*/
public boolean hasKerning() {
return hasKerning(address);
}
private static native boolean hasKerning(long face); /*
return FT_HAS_KERNING(((FT_Face)face));
*/
public int getKerning(int leftGlyph, int rightGlyph, int kernMode) {
return getKerning(address, leftGlyph, rightGlyph, kernMode);
}
private static native int getKerning(long face, int leftGlyph, int rightGlyph, int kernMode); /*
FT_Vector kerning;
FT_Error error = FT_Get_Kerning((FT_Face)face, leftGlyph, rightGlyph, kernMode, &kerning);
if(error) return 0;
return kerning.x;
*/
public int getCharIndex(int charCode) {
return getCharIndex(address, charCode);
}
private static native int getCharIndex(long face, int charCode); /*
return FT_Get_Char_Index((FT_Face)face, charCode);
*/
}
public static class Size extends Pointer {
Size (long address) {
super(address);
}
public SizeMetrics getMetrics() {
return new SizeMetrics(getMetrics(address));
}
private static native long getMetrics(long address); /*
return (jlong)&((FT_Size)address)->metrics;
*/
}
public static class SizeMetrics extends Pointer {
SizeMetrics (long address) {
super(address);
}
public int getXppem() {
return getXppem(address);
}
private static native int getXppem(long metrics); /*
return ((FT_Size_Metrics*)metrics)->x_ppem;
*/
public int getYppem() {
return getYppem(address);
}
private static native int getYppem(long metrics); /*
return ((FT_Size_Metrics*)metrics)->y_ppem;
*/
public int getXScale() {
return getXscale(address);
}
private static native int getXscale(long metrics); /*
return ((FT_Size_Metrics*)metrics)->x_scale;
*/
public int getYscale() {
return getYscale(address);
}
private static native int getYscale(long metrics); /*
return ((FT_Size_Metrics*)metrics)->x_scale;
*/
public int getAscender() {
return getAscender(address);
}
private static native int getAscender(long metrics); /*
return ((FT_Size_Metrics*)metrics)->ascender;
*/
public int getDescender() {
return getDescender(address);
}
private static native int getDescender(long metrics); /*
return ((FT_Size_Metrics*)metrics)->descender;
*/
public int getHeight() {
return getHeight(address);
}
private static native int getHeight(long metrics); /*
return ((FT_Size_Metrics*)metrics)->height;
*/
public int getMaxAdvance() {
return getMaxAdvance(address);
}
private static native int getMaxAdvance(long metrics); /*
return ((FT_Size_Metrics*)metrics)->max_advance;
*/
}
public static class GlyphSlot extends Pointer {
GlyphSlot (long address) {
super(address);
}
public void dispose () {
done(address);
}
private static native void done(long glyph); /*
FT_Done_GlyphSlot((FT_GlyphSlot)glyph);
*/
public GlyphMetrics getMetrics() {
return new GlyphMetrics(getMetrics(address));
}
private static native long getMetrics(long slot); /*
return (jlong)&((FT_GlyphSlot)slot)->metrics;
*/
public int getLinearHoriAdvance() {
return getLinearHoriAdvance(address);
}
private static native int getLinearHoriAdvance(long slot); /*
return ((FT_GlyphSlot)slot)->linearHoriAdvance;
*/
public int getLinearVertAdvance() {
return getLinearVertAdvance(address);
}
private static native int getLinearVertAdvance(long slot); /*
return ((FT_GlyphSlot)slot)->linearVertAdvance;
*/
public int getAdvanceX() {
return getAdvanceX(address);
}
private static native int getAdvanceX(long slot); /*
return ((FT_GlyphSlot)slot)->advance.x;
*/
public int getAdvanceY() {
return getAdvanceY(address);
}
private static native int getAdvanceY(long slot); /*
return ((FT_GlyphSlot)slot)->advance.y;
*/
public int getFormat() {
return getFormat(address);
}
private static native int getFormat(long slot); /*
return ((FT_GlyphSlot)slot)->format;
*/
public Bitmap getBitmap() {
return new Bitmap(getBitmap(address));
}
private static native long getBitmap(long slot); /*
FT_GlyphSlot glyph = ((FT_GlyphSlot)slot);
return (jlong)&(glyph->bitmap);
*/
public int getBitmapLeft() {
return getBitmapLeft(address);
}
private static native int getBitmapLeft(long slot); /*
return ((FT_GlyphSlot)slot)->bitmap_left;
*/
public int getBitmapTop() {
return getBitmapTop(address);
}
private static native int getBitmapTop(long slot); /*
return ((FT_GlyphSlot)slot)->bitmap_top;
*/
public boolean renderGlyph(int renderMode) {
return renderGlyph(address, renderMode);
}
private static native boolean renderGlyph(long slot, int renderMode); /*
return !FT_Render_Glyph((FT_GlyphSlot)slot, (FT_Render_Mode)renderMode);
*/
public Glyph getGlyph() {
long glyph = getGlyph(address);
if(glyph == 0) throw new RuntimeException("Couldn't get glyph");
return new Glyph(glyph);
}
private static native long getGlyph(long glyphSlot); /*
FT_Glyph glyph;
FT_Error error = FT_Get_Glyph((FT_GlyphSlot)glyphSlot, &glyph);
if(error) return 0;
else return (jlong)glyph;
*/
}
public static class Glyph extends Pointer {
private boolean rendered;
Glyph (long address) {
super(address);
}
public void dispose () {
done(address);
}
private static native void done(long glyph); /*
FT_Done_Glyph((FT_Glyph)glyph);
*/
public void strokeBorder(Stroker stroker, boolean inside) {
address = strokeBorder(address, stroker.address, inside);
}
private static native long strokeBorder(long glyph, long stroker, boolean inside); /*
FT_Glyph border_glyph = (FT_Glyph)glyph;
FT_Glyph_StrokeBorder(&border_glyph, (FT_Stroker)stroker, inside, 1);
return (jlong)border_glyph;
*/
public void toBitmap(int renderMode) {
long bitmap = toBitmap(address, renderMode);
if (bitmap == 0) throw new RuntimeException("Couldn't render glyph");
address = bitmap;
rendered = true;
}
private static native long toBitmap(long glyph, int renderMode); /*
FT_Glyph bitmap = (FT_Glyph)glyph;
FT_Error error = FT_Glyph_To_Bitmap(&bitmap, (FT_Render_Mode)renderMode, NULL, 1);
if(error) return 0;
return (jlong)bitmap;
*/
public Bitmap getBitmap() {
if (!rendered) {
throw new RuntimeException("Glyph is not yet rendered");
}
return new Bitmap(getBitmap(address));
}
private static native long getBitmap(long glyph); /*
FT_BitmapGlyph glyph_bitmap = ((FT_BitmapGlyph)glyph);
return (jlong)&(glyph_bitmap->bitmap);
*/
public int getLeft() {
if (!rendered) {
throw new RuntimeException("Glyph is not yet rendered");
}
return getLeft(address);
}
private static native int getLeft(long glyph); /*
FT_BitmapGlyph glyph_bitmap = ((FT_BitmapGlyph)glyph);
return glyph_bitmap->left;
*/
public int getTop() {
if (!rendered) {
throw new RuntimeException("Glyph is not yet rendered");
}
return getTop(address);
}
private static native int getTop(long glyph); /*
FT_BitmapGlyph glyph_bitmap = ((FT_BitmapGlyph)glyph);
return glyph_bitmap->top;
*/
}
public static class Bitmap extends Pointer {
Bitmap (long address) {
super(address);
}
public int getRows() {
return getRows(address);
}
private static native int getRows(long bitmap); /*
return ((FT_Bitmap*)bitmap)->rows;
*/
public int getWidth() {
return getWidth(address);
}
private static native int getWidth(long bitmap); /*
return ((FT_Bitmap*)bitmap)->width;
*/
public int getPitch() {
return getPitch(address);
}
private static native int getPitch(long bitmap); /*
return ((FT_Bitmap*)bitmap)->pitch;
*/
public ByteBuffer getBuffer() {
if (getRows() == 0)
// Issue #768 - CheckJNI frowns upon env->NewDirectByteBuffer with NULL buffer or capacity 0
// "JNI WARNING: invalid values for address (0x0) or capacity (0)"
// FreeType sets FT_Bitmap::buffer to NULL when the bitmap is empty (e.g. for ' ')
// JNICheck is on by default on emulators and might have a point anyway...
// So let's avoid this and just return a dummy non-null non-zero buffer
return ByteBuffer.allocateDirect(1);
return getBuffer(address);
}
private static native ByteBuffer getBuffer(long bitmap); /*
FT_Bitmap* bmp = (FT_Bitmap*)bitmap;
return env->NewDirectByteBuffer((void*)bmp->buffer, bmp->rows * abs(bmp->pitch));
*/
public int getNumGray() {
return getNumGray(address);
}
private static native int getNumGray(long bitmap); /*
return ((FT_Bitmap*)bitmap)->num_grays;
*/
public int getPixelMode() {
return getPixelMode(address);
}
private static native int getPixelMode(long bitmap); /*
return ((FT_Bitmap*)bitmap)->pixel_mode;
*/
}
public static class GlyphMetrics extends Pointer {
GlyphMetrics (long address) {
super(address);
}
public int getWidth() {
return getWidth(address);
}
private static native int getWidth(long metrics); /*
return ((FT_Glyph_Metrics*)metrics)->width;
*/
public int getHeight() {
return getHeight(address);
}
private static native int getHeight(long metrics); /*
return ((FT_Glyph_Metrics*)metrics)->height;
*/
public int getHoriBearingX() {
return getHoriBearingX(address);
}
private static native int getHoriBearingX(long metrics); /*
return ((FT_Glyph_Metrics*)metrics)->horiBearingX;
*/
public int getHoriBearingY() {
return getHoriBearingY(address);
}
private static native int getHoriBearingY(long metrics); /*
return ((FT_Glyph_Metrics*)metrics)->horiBearingY;
*/
public int getHoriAdvance() {
return getHoriAdvance(address);
}
private static native int getHoriAdvance(long metrics); /*
return ((FT_Glyph_Metrics*)metrics)->horiAdvance;
*/
public int getVertBearingX() {
return getVertBearingX(address);
}
private static native int getVertBearingX(long metrics); /*
return ((FT_Glyph_Metrics*)metrics)->vertBearingX;
*/
public int getVertBearingY() {
return getVertBearingY(address);
}
private static native int getVertBearingY(long metrics); /*
return ((FT_Glyph_Metrics*)metrics)->vertBearingY;
*/
public int getVertAdvance() {
return getVertAdvance(address);
}
private static native int getVertAdvance(long metrics); /*
return ((FT_Glyph_Metrics*)metrics)->vertAdvance;
*/
}
public static class Stroker extends Pointer {
Stroker(long address) {
super(address);
}
public void set(int radius, int lineCap, int lineJoin, int miterLimit) {
set(address, radius, lineCap, lineJoin, miterLimit);
}
private static native void set(long stroker, int radius, int lineCap, int lineJoin, int miterLimit); /*
FT_Stroker_Set((FT_Stroker)stroker, radius, (FT_Stroker_LineCap)lineCap, (FT_Stroker_LineJoin)lineJoin, miterLimit);
*/
public void dispose() {
done(address);
}
private static native void done(long stroker); /*
FT_Stroker_Done((FT_Stroker)stroker);
*/
}
public static int FT_PIXEL_MODE_NONE = 0;
public static int FT_PIXEL_MODE_MONO = 1;
public static int FT_PIXEL_MODE_GRAY = 2;
public static int FT_PIXEL_MODE_GRAY2 = 3;
public static int FT_PIXEL_MODE_GRAY4 = 4;
public static int FT_PIXEL_MODE_LCD = 5;
public static int FT_PIXEL_MODE_LCD_V = 6;
private static int encode (char a, char b, char c, char d) {
return (a << 24) | (b << 16) | (c << 8) | d;
}
public static int FT_ENCODING_NONE = 0;
public static int FT_ENCODING_MS_SYMBOL = encode('s', 'y', 'm', 'b');
public static int FT_ENCODING_UNICODE = encode('u', 'n', 'i', 'c');
public static int FT_ENCODING_SJIS = encode('s', 'j', 'i', 's');
public static int FT_ENCODING_GB2312 = encode('g', 'b', ' ', ' ');
public static int FT_ENCODING_BIG5 = encode('b', 'i', 'g', '5');
public static int FT_ENCODING_WANSUNG = encode('w', 'a', 'n', 's');
public static int FT_ENCODING_JOHAB = encode('j', 'o', 'h', 'a');
public static int FT_ENCODING_ADOBE_STANDARD = encode('A', 'D', 'O', 'B');
public static int FT_ENCODING_ADOBE_EXPERT = encode('A', 'D', 'B', 'E');
public static int FT_ENCODING_ADOBE_CUSTOM = encode('A', 'D', 'B', 'C');
public static int FT_ENCODING_ADOBE_LATIN_1 = encode('l', 'a', 't', '1');
public static int FT_ENCODING_OLD_LATIN_2 = encode('l', 'a', 't', '2');
public static int FT_ENCODING_APPLE_ROMAN = encode('a', 'r', 'm', 'n');
public static int FT_FACE_FLAG_SCALABLE = ( 1 << 0 );
public static int FT_FACE_FLAG_FIXED_SIZES = ( 1 << 1 );
public static int FT_FACE_FLAG_FIXED_WIDTH = ( 1 << 2 );
public static int FT_FACE_FLAG_SFNT = ( 1 << 3 );
public static int FT_FACE_FLAG_HORIZONTAL = ( 1 << 4 );
public static int FT_FACE_FLAG_VERTICAL = ( 1 << 5 );
public static int FT_FACE_FLAG_KERNING = ( 1 << 6 );
public static int FT_FACE_FLAG_FAST_GLYPHS = ( 1 << 7 );
public static int FT_FACE_FLAG_MULTIPLE_MASTERS = ( 1 << 8 );
public static int FT_FACE_FLAG_GLYPH_NAMES = ( 1 << 9 );
public static int FT_FACE_FLAG_EXTERNAL_STREAM = ( 1 << 10 );
public static int FT_FACE_FLAG_HINTER = ( 1 << 11 );
public static int FT_FACE_FLAG_CID_KEYED = ( 1 << 12 );
public static int FT_FACE_FLAG_TRICKY = ( 1 << 13 );
public static int FT_STYLE_FLAG_ITALIC = ( 1 << 0 );
public static int FT_STYLE_FLAG_BOLD = ( 1 << 1 );
public static int FT_LOAD_DEFAULT = 0x0;
public static int FT_LOAD_NO_SCALE = 0x1;
public static int FT_LOAD_NO_HINTING = 0x2;
public static int FT_LOAD_RENDER = 0x4;
public static int FT_LOAD_NO_BITMAP = 0x8;
public static int FT_LOAD_VERTICAL_LAYOUT = 0x10;
public static int FT_LOAD_FORCE_AUTOHINT = 0x20;
public static int FT_LOAD_CROP_BITMAP = 0x40;
public static int FT_LOAD_PEDANTIC = 0x80;
public static int FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH = 0x200;
public static int FT_LOAD_NO_RECURSE = 0x400;
public static int FT_LOAD_IGNORE_TRANSFORM = 0x800;
public static int FT_LOAD_MONOCHROME = 0x1000;
public static int FT_LOAD_LINEAR_DESIGN = 0x2000;
public static int FT_LOAD_NO_AUTOHINT = 0x8000;
public static int FT_RENDER_MODE_NORMAL = 0;
public static int FT_RENDER_MODE_LIGHT = 1;
public static int FT_RENDER_MODE_MONO = 2;
public static int FT_RENDER_MODE_LCD = 3;
public static int FT_RENDER_MODE_LCD_V = 4;
public static int FT_RENDER_MODE_MAX = 5;
public static int FT_KERNING_DEFAULT = 0;
public static int FT_KERNING_UNFITTED = 1;
public static int FT_KERNING_UNSCALED = 2;
public static int FT_STROKER_LINECAP_BUTT = 0;
public static int FT_STROKER_LINECAP_ROUND = 1;
public static int FT_STROKER_LINECAP_SQUARE = 2;
public static int FT_STROKER_LINEJOIN_ROUND = 0;
public static int FT_STROKER_LINEJOIN_BEVEL = 1;
public static int FT_STROKER_LINEJOIN_MITER_VARIABLE = 2;
public static int FT_STROKER_LINEJOIN_MITER = FT_STROKER_LINEJOIN_MITER_VARIABLE;
public static int FT_STROKER_LINEJOIN_MITER_FIXED = 3;
public static Library initFreeType() {
Lib.init();
long address = initFreeTypeJni();
if(address == 0) throw new RuntimeException("Couldn't initialize FreeType library");
else return new Library(address);
}
private static native long initFreeTypeJni(); /*
FT_Library library = 0;
FT_Error error = FT_Init_FreeType(&library);
if(error) return 0;
else return (jlong)library;
*/
public static int toInt (int value) {
if (value < 0) return (int)((value - 32) >> 6);
return (int)((value + 32) >> 6);
}
}