Improve system for Font rendering, need to improve charCode -> glyphIndex mapping though
This commit is contained in:
@@ -66,6 +66,8 @@ class Image {
|
||||
public var transparent (get, set):Bool;
|
||||
public var type:ImageType;
|
||||
public var width:Int;
|
||||
public var x:Float;
|
||||
public var y:Float;
|
||||
|
||||
|
||||
public function new (buffer:ImageBuffer = null, offsetX:Int = 0, offsetY:Int = 0, width:Int = -1, height:Int = -1, color:Null<Int> = null, type:ImageType = null) {
|
||||
|
||||
@@ -75,6 +75,17 @@ class Font {
|
||||
}
|
||||
|
||||
|
||||
public function getCharIndex (char:String):Int {
|
||||
|
||||
#if (cpp || neko || nodejs)
|
||||
return lime_font_get_char_index (__handle, char);
|
||||
#else
|
||||
return -1;
|
||||
#end
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function getGlyphMetrics (glyphs:GlyphSet = null):Map<Int, Glyph> {
|
||||
|
||||
if (glyphs == null) {
|
||||
@@ -89,7 +100,7 @@ class Font {
|
||||
|
||||
for (value in array) {
|
||||
|
||||
var glyph = new Glyph (value.charCode, value.glyphIndex);
|
||||
var glyph = new Glyph (value.charCode, value.index);
|
||||
var metrics = new GlyphMetrics ();
|
||||
|
||||
metrics.height = value.height;
|
||||
@@ -102,7 +113,7 @@ class Font {
|
||||
|
||||
glyph.metrics = metrics;
|
||||
|
||||
map.set (glyph.glyphIndex, glyph);
|
||||
map.set (glyph.index, glyph);
|
||||
|
||||
}
|
||||
|
||||
@@ -114,41 +125,178 @@ class Font {
|
||||
}
|
||||
|
||||
|
||||
public function renderGlyphs (fontSize:Int, glyphs:GlyphSet = null):Map<Int, Glyph> {
|
||||
|
||||
if (glyphs == null) {
|
||||
|
||||
glyphs = new GlyphSet ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^`'\"/\\&*()[]{}<>|:;_-+=?,. ");
|
||||
|
||||
}
|
||||
public function renderGlyph (index:Int, fontSize:Int):Image {
|
||||
|
||||
#if (cpp || neko || nodejs)
|
||||
|
||||
var data = lime_font_create_images (__handle, fontSize, glyphs);
|
||||
lime_font_set_size (__handle, fontSize);
|
||||
|
||||
if (data == null) {
|
||||
var bytes = new ByteArray ();
|
||||
bytes.bigEndian = false;
|
||||
|
||||
return null;
|
||||
if (lime_font_render_glyph (__handle, index, bytes)) {
|
||||
|
||||
} else {
|
||||
bytes.position = 0;
|
||||
|
||||
var buffer = new ImageBuffer (new UInt8Array (data.image.data), data.image.width, data.image.height, data.image.bpp);
|
||||
var map = new Map<Int, Glyph> ();
|
||||
var index = bytes.readUnsignedInt ();
|
||||
var width = bytes.readUnsignedInt ();
|
||||
var height = bytes.readUnsignedInt ();
|
||||
var x = bytes.readUnsignedInt ();
|
||||
var y = bytes.readUnsignedInt ();
|
||||
|
||||
for (glyphData in cast (data.glyphs, Array<Dynamic>)) {
|
||||
var data = new ByteArray (width * height);
|
||||
bytes.readBytes (data, 0, width * height);
|
||||
|
||||
if (glyphData != null) {
|
||||
var buffer = new ImageBuffer (new UInt8Array (data), width, height, 1);
|
||||
var image = new Image (buffer, 0, 0, width, height);
|
||||
image.x = x;
|
||||
image.y = y;
|
||||
|
||||
var glyph = new Glyph (glyphData.charCode, glyphData.glyphIndex);
|
||||
glyph.image = new Image (buffer, glyphData.x, glyphData.y, glyphData.width, glyphData.height);
|
||||
glyph.x = glyphData.offset.x;
|
||||
glyph.y = glyphData.offset.y;
|
||||
map.set (glyph.glyphIndex, glyph);
|
||||
return image;
|
||||
|
||||
}
|
||||
|
||||
#end
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function renderGlyphs (indices:Array<Int>, fontSize:Int):Map<Int, Image> {
|
||||
|
||||
#if (cpp || neko || nodejs)
|
||||
|
||||
lime_font_set_size (__handle, fontSize);
|
||||
|
||||
var bytes = new ByteArray ();
|
||||
bytes.bigEndian = false;
|
||||
|
||||
if (lime_font_render_glyphs (__handle, indices, bytes)) {
|
||||
|
||||
bytes.position = 0;
|
||||
|
||||
var count = bytes.readUnsignedInt ();
|
||||
|
||||
var bufferWidth = 128;
|
||||
var bufferHeight = 128;
|
||||
var offsetX = 0;
|
||||
var offsetY = 0;
|
||||
var maxRows = 0;
|
||||
|
||||
var width, height;
|
||||
var i = 0;
|
||||
|
||||
while (i < count) {
|
||||
|
||||
bytes.position += 4;
|
||||
width = bytes.readUnsignedInt ();
|
||||
height = bytes.readUnsignedInt ();
|
||||
bytes.position += (4 * 2) + width * height;
|
||||
|
||||
if (offsetX + width > bufferWidth) {
|
||||
|
||||
offsetY += maxRows + 1;
|
||||
offsetX = 0;
|
||||
maxRows = 0;
|
||||
|
||||
}
|
||||
|
||||
if (offsetY + height > bufferHeight) {
|
||||
|
||||
if (bufferWidth < bufferHeight) {
|
||||
|
||||
bufferWidth *= 2;
|
||||
|
||||
} else {
|
||||
|
||||
bufferHeight *= 2;
|
||||
|
||||
}
|
||||
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
maxRows = 0;
|
||||
|
||||
// TODO: make this better
|
||||
|
||||
bytes.position = 4;
|
||||
i = 0;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
offsetX += width + 1;
|
||||
|
||||
if (height > maxRows) {
|
||||
|
||||
maxRows = height;
|
||||
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
var map = new Map <Int, Image> ();
|
||||
var buffer = new ImageBuffer (null, bufferWidth, bufferHeight, 1);
|
||||
var data = new ByteArray (bufferWidth * bufferHeight);
|
||||
|
||||
bytes.position = 4;
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
maxRows = 0;
|
||||
|
||||
var index, x, y, image;
|
||||
|
||||
for (i in 0...count) {
|
||||
|
||||
index = bytes.readUnsignedInt ();
|
||||
width = bytes.readUnsignedInt ();
|
||||
height = bytes.readUnsignedInt ();
|
||||
x = bytes.readUnsignedInt ();
|
||||
y = bytes.readUnsignedInt ();
|
||||
|
||||
if (offsetX + width > bufferWidth) {
|
||||
|
||||
offsetY += maxRows + 1;
|
||||
offsetX = 0;
|
||||
maxRows = 0;
|
||||
|
||||
}
|
||||
|
||||
for (i in 0...height) {
|
||||
|
||||
data.position = ((i + offsetY) * bufferWidth) + offsetX;
|
||||
//bytes.readBytes (data, 0, width);
|
||||
|
||||
for (x in 0...width) {
|
||||
|
||||
var byte = bytes.readUnsignedByte ();
|
||||
data.writeByte (byte);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
image = new Image (buffer, offsetX, offsetY, width, height);
|
||||
image.x = x;
|
||||
image.y = y;
|
||||
|
||||
map.set (index, image);
|
||||
|
||||
offsetX += width + 1;
|
||||
|
||||
if (height > maxRows) {
|
||||
|
||||
maxRows = height;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
buffer.data = new UInt8Array (data);
|
||||
|
||||
return map;
|
||||
|
||||
}
|
||||
@@ -291,6 +439,7 @@ class Font {
|
||||
|
||||
#if (cpp || neko || nodejs)
|
||||
private static var lime_font_get_ascender = System.load ("lime", "lime_font_get_ascender", 1);
|
||||
private static var lime_font_get_char_index = System.load ("lime", "lime_font_get_char_index", 2);
|
||||
private static var lime_font_get_descender = System.load ("lime", "lime_font_get_descender", 1);
|
||||
private static var lime_font_get_family_name = System.load ("lime", "lime_font_get_family_name", 1);
|
||||
private static var lime_font_get_glyph_metrics = System.load ("lime", "lime_font_get_glyph_metrics", 2);
|
||||
@@ -300,8 +449,10 @@ class Font {
|
||||
private static var lime_font_get_underline_thickness = System.load ("lime", "lime_font_get_underline_thickness", 1);
|
||||
private static var lime_font_get_units_per_em = System.load ("lime", "lime_font_get_units_per_em", 1);
|
||||
private static var lime_font_load:Dynamic = System.load ("lime", "lime_font_load", 1);
|
||||
private static var lime_font_create_images = System.load ("lime", "lime_font_create_images", 3);
|
||||
private static var lime_font_outline_decompose = System.load ("lime", "lime_font_outline_decompose", 2);
|
||||
private static var lime_font_render_glyph = System.load ("lime", "lime_font_render_glyph", 3);
|
||||
private static var lime_font_render_glyphs = System.load ("lime", "lime_font_render_glyphs", 3);
|
||||
private static var lime_font_set_size = System.load ("lime", "lime_font_set_size", 2);
|
||||
#end
|
||||
|
||||
|
||||
|
||||
@@ -8,17 +8,17 @@ class Glyph {
|
||||
|
||||
|
||||
public var charCode:Int;
|
||||
public var glyphIndex:Int;
|
||||
public var image:Image;
|
||||
public var index:Int;
|
||||
public var metrics:GlyphMetrics;
|
||||
public var x:Int;
|
||||
public var y:Int;
|
||||
|
||||
|
||||
public function new (charCode:Int = 0, glyphIndex:Int = 0) {
|
||||
public function new (charCode:Int = -1, index:Int = -1) {
|
||||
|
||||
this.charCode = charCode;
|
||||
this.glyphIndex = glyphIndex;
|
||||
this.index = index;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -44,4 +44,271 @@ namespace lime {
|
||||
}
|
||||
|
||||
|
||||
#ifndef HX_WINDOWS
|
||||
#include <stdint.h>
|
||||
#else
|
||||
|
||||
|
||||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2013 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the product nor the names of its contributors may
|
||||
// be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if _MSC_VER >= 1600 // [
|
||||
#include <stdint.h>
|
||||
#else // ] _MSC_VER >= 1600 [
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
|
||||
// Check out Issue 9 for the details.
|
||||
#ifndef INTMAX_C // [
|
||||
# define INTMAX_C INT64_C
|
||||
#endif // INTMAX_C ]
|
||||
#ifndef UINTMAX_C // [
|
||||
# define UINTMAX_C UINT64_C
|
||||
#endif // UINTMAX_C ]
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
#endif // _MSC_VER >= 1600 ]
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
|
||||
#include <graphics/ImageBuffer.h>
|
||||
#include <system/System.h>
|
||||
#include <text/GlyphSet.h>
|
||||
#include <utils/Resource.h>
|
||||
#include <hx/CFFI.h>
|
||||
@@ -21,6 +22,18 @@ namespace lime {
|
||||
} GlyphInfo;
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
uint32_t index;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
unsigned char data;
|
||||
|
||||
} GlyphImage;
|
||||
|
||||
|
||||
class Font {
|
||||
|
||||
|
||||
@@ -30,9 +43,9 @@ namespace lime {
|
||||
Font (Resource *resource, int faceIndex = 0);
|
||||
~Font ();
|
||||
|
||||
value CreateImages (int fontSize, GlyphSet *glyphSet, ImageBuffer *image);
|
||||
value Decompose (int em);
|
||||
int GetAscender ();
|
||||
int GetCharIndex (char* character);
|
||||
int GetDescender ();
|
||||
wchar_t *GetFamilyName ();
|
||||
value GetGlyphMetrics (GlyphSet *glyphSet);
|
||||
@@ -41,6 +54,8 @@ namespace lime {
|
||||
int GetUnderlinePosition ();
|
||||
int GetUnderlineThickness ();
|
||||
int GetUnitsPerEM ();
|
||||
int RenderGlyph (int index, ByteArray *bytes, int offset = 0);
|
||||
int RenderGlyphs (value indices, ByteArray *bytes);
|
||||
void SetSize (size_t size);
|
||||
|
||||
void* face;
|
||||
|
||||
267
project/include/utils/stdint.h
Normal file
267
project/include/utils/stdint.h
Normal file
@@ -0,0 +1,267 @@
|
||||
#ifndef HX_WINDOWS
|
||||
#include <stdint.h>
|
||||
#else
|
||||
|
||||
|
||||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2013 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the product nor the names of its contributors may
|
||||
// be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if _MSC_VER >= 1600 // [
|
||||
#include <stdint.h>
|
||||
#else // ] _MSC_VER >= 1600 [
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
|
||||
// Check out Issue 9 for the details.
|
||||
#ifndef INTMAX_C // [
|
||||
# define INTMAX_C INT64_C
|
||||
#endif // INTMAX_C ]
|
||||
#ifndef UINTMAX_C // [
|
||||
# define UINTMAX_C UINT64_C
|
||||
#endif // UINTMAX_C ]
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
#endif // _MSC_VER >= 1600 ]
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
|
||||
|
||||
#endif
|
||||
@@ -120,23 +120,6 @@ namespace lime {
|
||||
}
|
||||
|
||||
|
||||
value lime_font_create_images (value fontHandle, value fontSize, value glyphSet) {
|
||||
|
||||
#ifdef LIME_FREETYPE
|
||||
ImageBuffer image;
|
||||
Font *font = (Font*)(intptr_t)val_float (fontHandle);
|
||||
GlyphSet glyphs = GlyphSet (glyphSet);
|
||||
value data = alloc_empty_object ();
|
||||
alloc_field (data, val_id ("glyphs"), font->CreateImages (val_int (fontSize), &glyphs, &image));
|
||||
alloc_field (data, val_id ("image"), image.Value ());
|
||||
return data;
|
||||
#else
|
||||
return alloc_null ();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void lime_font_destroy (value handle) {
|
||||
|
||||
Font *font = (Font*)(intptr_t)val_float (handle);
|
||||
@@ -158,6 +141,18 @@ namespace lime {
|
||||
}
|
||||
|
||||
|
||||
value lime_font_get_char_index (value fontHandle, value character) {
|
||||
|
||||
#ifdef LIME_FREETYPE
|
||||
Font *font = (Font*)(intptr_t)val_float (fontHandle);
|
||||
return alloc_int (font->GetCharIndex ((char*)val_wstring (character)));
|
||||
#else
|
||||
return alloc_int (-1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
value lime_font_get_descender (value fontHandle) {
|
||||
|
||||
#ifdef LIME_FREETYPE
|
||||
@@ -299,6 +294,44 @@ namespace lime {
|
||||
}
|
||||
|
||||
|
||||
value lime_font_render_glyph (value fontHandle, value index, value data) {
|
||||
|
||||
#ifdef LIME_FREETYPE
|
||||
Font *font = (Font*)(intptr_t)val_float (fontHandle);
|
||||
ByteArray bytes = ByteArray (data);
|
||||
return alloc_bool (font->RenderGlyph (val_int (index), &bytes));
|
||||
#else
|
||||
return alloc_bool (false);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
value lime_font_render_glyphs (value fontHandle, value indices, value data) {
|
||||
|
||||
#ifdef LIME_FREETYPE
|
||||
Font *font = (Font*)(intptr_t)val_float (fontHandle);
|
||||
ByteArray bytes = ByteArray (data);
|
||||
return alloc_bool (font->RenderGlyphs (indices, &bytes));
|
||||
#else
|
||||
return alloc_bool (false);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
value lime_font_set_size (value fontHandle, value fontSize) {
|
||||
|
||||
#ifdef LIME_FREETYPE
|
||||
Font *font = (Font*)(intptr_t)val_float (fontHandle);
|
||||
font->SetSize (val_int (fontSize));
|
||||
#endif
|
||||
|
||||
return alloc_null ();
|
||||
|
||||
}
|
||||
|
||||
|
||||
value lime_image_encode (value buffer, value type, value quality) {
|
||||
|
||||
ImageBuffer imageBuffer = ImageBuffer (buffer);
|
||||
@@ -624,8 +657,8 @@ namespace lime {
|
||||
DEFINE_PRIM (lime_application_quit, 1);
|
||||
DEFINE_PRIM (lime_application_update, 1);
|
||||
DEFINE_PRIM (lime_audio_load, 1);
|
||||
DEFINE_PRIM (lime_font_create_images, 3);
|
||||
DEFINE_PRIM (lime_font_get_ascender, 1);
|
||||
DEFINE_PRIM (lime_font_get_char_index, 2);
|
||||
DEFINE_PRIM (lime_font_get_descender, 1);
|
||||
DEFINE_PRIM (lime_font_get_family_name, 1);
|
||||
DEFINE_PRIM (lime_font_get_glyph_metrics, 2);
|
||||
@@ -636,6 +669,9 @@ namespace lime {
|
||||
DEFINE_PRIM (lime_font_get_units_per_em, 1);
|
||||
DEFINE_PRIM (lime_font_load, 1);
|
||||
DEFINE_PRIM (lime_font_outline_decompose, 2);
|
||||
DEFINE_PRIM (lime_font_render_glyph, 3);
|
||||
DEFINE_PRIM (lime_font_render_glyphs, 3);
|
||||
DEFINE_PRIM (lime_font_set_size, 2);
|
||||
DEFINE_PRIM (lime_image_encode, 3);
|
||||
DEFINE_PRIM (lime_image_load, 1);
|
||||
DEFINE_PRIM (lime_jni_getenv, 0);
|
||||
|
||||
@@ -17,6 +17,117 @@
|
||||
#endif
|
||||
|
||||
|
||||
// from http://stackoverflow.com/questions/2948308/how-do-i-read-utf-8-characters-via-a-pointer
|
||||
#define IS_IN_RANGE(c, f, l) (((c) >= (f)) && ((c) <= (l)))
|
||||
|
||||
|
||||
unsigned long readNextChar (char*& p)
|
||||
{
|
||||
// TODO: since UTF-8 is a variable-length
|
||||
// encoding, you should pass in the input
|
||||
// buffer's actual byte length so that you
|
||||
// can determine if a malformed UTF-8
|
||||
// sequence would exceed the end of the buffer...
|
||||
|
||||
unsigned char c1, c2, *ptr = (unsigned char*) p;
|
||||
unsigned long uc = 0;
|
||||
int seqlen;
|
||||
|
||||
c1 = ptr[0];
|
||||
|
||||
if ((c1 & 0x80) == 0) {
|
||||
|
||||
uc = (unsigned long) (c1 & 0x7F);
|
||||
seqlen = 1;
|
||||
|
||||
} else if ((c1 & 0xE0) == 0xC0) {
|
||||
|
||||
uc = (unsigned long) (c1 & 0x1F);
|
||||
seqlen = 2;
|
||||
|
||||
} else if ((c1 & 0xF0) == 0xE0) {
|
||||
|
||||
uc = (unsigned long) (c1 & 0x0F);
|
||||
seqlen = 3;
|
||||
|
||||
} else if ((c1 & 0xF8) == 0xF0) {
|
||||
|
||||
uc = (unsigned long) (c1 & 0x07);
|
||||
seqlen = 4;
|
||||
|
||||
} else {
|
||||
|
||||
// malformed data, do something !!!
|
||||
return (unsigned long) -1;
|
||||
|
||||
}
|
||||
|
||||
for (int i = 1; i < seqlen; ++i) {
|
||||
|
||||
c1 = ptr[i];
|
||||
|
||||
if ((c1 & 0xC0) != 0x80) {
|
||||
|
||||
// malformed data, do something !!!
|
||||
return (unsigned long) -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch (seqlen) {
|
||||
case 2:
|
||||
c1 = ptr[0];
|
||||
|
||||
if (!IS_IN_RANGE(c1, 0xC2, 0xDF)) {
|
||||
|
||||
// malformed data, do something !!!
|
||||
return (unsigned long) -1;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
c1 = ptr[0];
|
||||
c2 = ptr[1];
|
||||
|
||||
if (((c1 == 0xE0) && !IS_IN_RANGE(c2, 0xA0, 0xBF)) ||
|
||||
((c1 == 0xED) && !IS_IN_RANGE(c2, 0x80, 0x9F)) ||
|
||||
(!IS_IN_RANGE(c1, 0xE1, 0xEC) && !IS_IN_RANGE(c1, 0xEE, 0xEF))) {
|
||||
|
||||
// malformed data, do something !!!
|
||||
return (unsigned long) -1;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case 4:
|
||||
c1 = ptr[0];
|
||||
c2 = ptr[1];
|
||||
|
||||
if (((c1 == 0xF0) && !IS_IN_RANGE(c2, 0x90, 0xBF)) ||
|
||||
((c1 == 0xF4) && !IS_IN_RANGE(c2, 0x80, 0x8F)) ||
|
||||
!IS_IN_RANGE(c1, 0xF1, 0xF3)) {
|
||||
|
||||
// malformed data, do something !!!
|
||||
return (unsigned long) -1;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 1; i < seqlen; ++i) {
|
||||
|
||||
uc = ((uc << 6) | (unsigned long)(ptr[i] & 0x3F));
|
||||
|
||||
}
|
||||
|
||||
p += seqlen;
|
||||
return uc;
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -159,14 +270,18 @@ namespace {
|
||||
namespace lime {
|
||||
|
||||
|
||||
static int id_buffer;
|
||||
static int id_charCode;
|
||||
static int id_codepoint;
|
||||
static int id_glyphIndex;
|
||||
static int id_height;
|
||||
static int id_index;
|
||||
static int id_horizontalAdvance;
|
||||
static int id_horizontalBearingX;
|
||||
static int id_horizontalBearingY;
|
||||
static int id_image;
|
||||
static int id_offset;
|
||||
static int id_offsetX;
|
||||
static int id_offsetY;
|
||||
static int id_size;
|
||||
static int id_verticalAdvance;
|
||||
static int id_verticalBearingX;
|
||||
@@ -189,11 +304,15 @@ namespace lime {
|
||||
id_size = val_id ("size");
|
||||
id_codepoint = val_id ("codepoint");
|
||||
|
||||
id_buffer = val_id ("buffer");
|
||||
id_charCode = val_id ("charCode");
|
||||
id_glyphIndex = val_id ("glyphIndex");
|
||||
id_horizontalAdvance = val_id ("horizontalAdvance");
|
||||
id_horizontalBearingX = val_id ("horizontalBearingX");
|
||||
id_horizontalBearingY = val_id ("horizontalBearingY");
|
||||
id_image = val_id ("image");
|
||||
id_index = val_id ("index");
|
||||
id_offsetX = val_id ("offsetX");
|
||||
id_offsetY = val_id ("offsetY");
|
||||
id_verticalAdvance = val_id ("verticalAdvance");
|
||||
id_verticalBearingX = val_id ("verticalBearingX");
|
||||
id_verticalBearingY = val_id ("verticalBearingY");
|
||||
@@ -341,193 +460,6 @@ namespace lime {
|
||||
}
|
||||
|
||||
|
||||
value Font::CreateImages (int fontSize, GlyphSet *glyphSet, ImageBuffer *image) {
|
||||
|
||||
initialize ();
|
||||
|
||||
std::list<FT_ULong> charCodes = std::list<FT_ULong> ();
|
||||
|
||||
if (!glyphSet->glyphs.empty ()) {
|
||||
|
||||
FT_ULong charCode;
|
||||
|
||||
for (unsigned int i = 0; i < glyphSet->glyphs.length (); i++) {
|
||||
|
||||
charCodes.push_back (glyphSet->glyphs[i]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GlyphRange range;
|
||||
|
||||
for (int i = 0; i < glyphSet->ranges.size (); i++) {
|
||||
|
||||
range = glyphSet->ranges[i];
|
||||
|
||||
if (range.start == 0 && range.end == -1) {
|
||||
|
||||
FT_UInt glyphIndex;
|
||||
FT_ULong charCode = FT_Get_First_Char ((FT_Face)face, &glyphIndex);
|
||||
|
||||
while (glyphIndex != 0) {
|
||||
|
||||
charCodes.push_back (charCode);
|
||||
charCode = FT_Get_Next_Char ((FT_Face)face, charCode, &glyphIndex);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
unsigned long end = range.end;
|
||||
|
||||
FT_ULong charCode = range.start;
|
||||
FT_UInt glyphIndex = FT_Get_Char_Index ((FT_Face)face, charCode);
|
||||
|
||||
while (charCode <= end || end < 0) {
|
||||
|
||||
if (glyphIndex > 0) {
|
||||
|
||||
charCodes.push_back (charCode);
|
||||
|
||||
}
|
||||
|
||||
glyphIndex = -1;
|
||||
charCode = FT_Get_Next_Char ((FT_Face)face, charCode, &glyphIndex);
|
||||
|
||||
if (glyphIndex == 0) {
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
charCodes.unique ();
|
||||
|
||||
image->Resize (128, 128, 1);
|
||||
int x = 0, y = 0, maxRows = 0;
|
||||
unsigned char *bytes = image->data->Bytes ();
|
||||
|
||||
value rects = alloc_array (charCodes.size ());
|
||||
int rectsIndex = 0;
|
||||
|
||||
size_t hdpi = 72;
|
||||
size_t vdpi = 72;
|
||||
size_t hres = 100;
|
||||
FT_Matrix matrix = {
|
||||
(int)((1.0/hres) * 0x10000L),
|
||||
(int)((0.0) * 0x10000L),
|
||||
(int)((0.0) * 0x10000L),
|
||||
(int)((1.0) * 0x10000L)
|
||||
};
|
||||
|
||||
FT_Set_Char_Size ((FT_Face)face, 0, (int)(fontSize*64), (int)(hdpi * hres), vdpi);
|
||||
FT_Set_Transform ((FT_Face)face, &matrix, NULL);
|
||||
FT_UInt glyphIndex;
|
||||
FT_ULong charCode;
|
||||
|
||||
for (std::list<FT_ULong>::iterator it = charCodes.begin (); it != charCodes.end (); it++) {
|
||||
|
||||
charCode = (*it);
|
||||
glyphIndex = FT_Get_Char_Index ((FT_Face)face, charCode);
|
||||
|
||||
FT_Load_Glyph ((FT_Face)face, glyphIndex, FT_LOAD_FORCE_AUTOHINT | FT_LOAD_DEFAULT);
|
||||
|
||||
if (FT_Render_Glyph (((FT_Face)face)->glyph, FT_RENDER_MODE_NORMAL) != 0) continue;
|
||||
|
||||
FT_Bitmap bitmap = ((FT_Face)face)->glyph->bitmap;
|
||||
|
||||
if (x + bitmap.width > image->width) {
|
||||
|
||||
y += maxRows + 1;
|
||||
x = maxRows = 0;
|
||||
|
||||
}
|
||||
|
||||
if (y + bitmap.rows > image->height) {
|
||||
|
||||
if (image->width < image->height) {
|
||||
|
||||
image->width *= 2;
|
||||
|
||||
} else {
|
||||
|
||||
image->height *= 2;
|
||||
|
||||
}
|
||||
|
||||
image->Resize (image->width, image->height, 1);
|
||||
rectsIndex = 0;
|
||||
it = charCodes.begin ();
|
||||
it--;
|
||||
x = y = maxRows = 0;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (image->bpp == 1) {
|
||||
|
||||
image->Blit (bitmap.buffer, x, y, bitmap.width, bitmap.rows);
|
||||
|
||||
} else {
|
||||
|
||||
for (int row = 0; row < bitmap.rows; row++) {
|
||||
|
||||
unsigned char *out = &bytes[((row + y) * image->width + x) * image->bpp];
|
||||
const unsigned char *line = &bitmap.buffer[row * bitmap.width]; // scanline
|
||||
const unsigned char *const end = line + bitmap.width;
|
||||
|
||||
while (line != end) {
|
||||
|
||||
*out++ = 0xFF;
|
||||
*out++ = 0xFF;
|
||||
*out++ = 0xFF;
|
||||
*out++ = *line;
|
||||
|
||||
line++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
value v = alloc_empty_object ();
|
||||
alloc_field (v, id_x, alloc_int (x));
|
||||
alloc_field (v, id_y, alloc_int (y));
|
||||
alloc_field (v, id_width, alloc_int (bitmap.width));
|
||||
alloc_field (v, id_height, alloc_int (bitmap.rows));
|
||||
|
||||
value offset = alloc_empty_object ();
|
||||
alloc_field (offset, id_x, alloc_int (((FT_Face)face)->glyph->bitmap_left));
|
||||
alloc_field (offset, id_y, alloc_int (((FT_Face)face)->glyph->bitmap_top));
|
||||
alloc_field (v, id_offset, offset);
|
||||
|
||||
alloc_field (v, id_charCode, alloc_int (charCode));
|
||||
alloc_field (v, id_glyphIndex, alloc_int (glyphIndex));
|
||||
//alloc_field (v, id_size, alloc_int ((*it).size));
|
||||
val_array_set_i (rects, rectsIndex++, v);
|
||||
|
||||
x += bitmap.width + 1;
|
||||
|
||||
if (bitmap.rows > maxRows) {
|
||||
|
||||
maxRows = bitmap.rows;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return rects;
|
||||
|
||||
}
|
||||
|
||||
|
||||
value Font::Decompose (int em) {
|
||||
|
||||
int result, i, j;
|
||||
@@ -699,6 +631,15 @@ namespace lime {
|
||||
}
|
||||
|
||||
|
||||
int Font::GetCharIndex (char* character) {
|
||||
|
||||
long charCode = readNextChar (character);
|
||||
|
||||
return FT_Get_Char_Index ((FT_Face)face, charCode);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int Font::GetDescender () {
|
||||
|
||||
return ((FT_Face)face)->descender;
|
||||
@@ -768,7 +709,7 @@ namespace lime {
|
||||
value metrics = alloc_empty_object ();
|
||||
|
||||
alloc_field (metrics, id_charCode, alloc_int (charCode));
|
||||
alloc_field (metrics, id_glyphIndex, alloc_int (glyphIndex));
|
||||
alloc_field (metrics, id_index, alloc_int (glyphIndex));
|
||||
alloc_field (metrics, id_height, alloc_int (((FT_Face)face)->glyph->metrics.height));
|
||||
alloc_field (metrics, id_horizontalBearingX, alloc_int (((FT_Face)face)->glyph->metrics.horiBearingX));
|
||||
alloc_field (metrics, id_horizontalBearingY, alloc_int (((FT_Face)face)->glyph->metrics.horiBearingY));
|
||||
@@ -891,6 +832,81 @@ namespace lime {
|
||||
}
|
||||
|
||||
|
||||
int Font::RenderGlyph (int index, ByteArray *bytes, int offset) {
|
||||
|
||||
FT_Load_Glyph ((FT_Face)face, index, FT_LOAD_FORCE_AUTOHINT | FT_LOAD_DEFAULT);
|
||||
|
||||
if (FT_Render_Glyph (((FT_Face)face)->glyph, FT_RENDER_MODE_NORMAL) == 0) {
|
||||
|
||||
FT_Bitmap bitmap = ((FT_Face)face)->glyph->bitmap;
|
||||
|
||||
int height = bitmap.rows;
|
||||
int width = bitmap.width;
|
||||
int pitch = bitmap.pitch;
|
||||
|
||||
if (width == 0 || height == 0) return 0;
|
||||
|
||||
uint32_t size = (4 * 5) + (width * height);
|
||||
|
||||
if (bytes->Size() < size + offset) {
|
||||
|
||||
bytes->Resize (size + offset);
|
||||
|
||||
}
|
||||
|
||||
GlyphImage *data = (GlyphImage*)(bytes->Bytes () + offset);
|
||||
|
||||
data->index = index;
|
||||
data->width = width;
|
||||
data->height = height;
|
||||
data->x = ((FT_Face)face)->glyph->bitmap_left;
|
||||
data->y = ((FT_Face)face)->glyph->bitmap_top;
|
||||
|
||||
unsigned char* position = &data->data;
|
||||
|
||||
for (int i = 0; i < height; i++) {
|
||||
|
||||
memcpy (position + (i * width), bitmap.buffer + (i * pitch), width);
|
||||
|
||||
}
|
||||
|
||||
return size;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int Font::RenderGlyphs (value indices, ByteArray *bytes) {
|
||||
|
||||
int offset = 0;
|
||||
int totalOffset = 4;
|
||||
uint32_t count = 0;
|
||||
|
||||
int numIndices = val_array_size (indices);
|
||||
|
||||
for (int i = 0; i < numIndices; i++) {
|
||||
|
||||
offset = RenderGlyph (val_int (val_array_i (indices, i)), bytes, totalOffset);
|
||||
|
||||
if (offset > 0) {
|
||||
|
||||
totalOffset += offset;
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*(bytes->Bytes ()) = count;
|
||||
|
||||
return totalOffset;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Font::SetSize (size_t size) {
|
||||
|
||||
size_t hdpi = 72;
|
||||
|
||||
Reference in New Issue
Block a user