Commit f16d5830 authored by Bernd Paysan's avatar Bernd Paysan

Added support for color emoji fonts

parent 1a764f7e
......@@ -18,7 +18,7 @@ AM_CPPFLAGS = $(EXAMPLE_CFLAGS) @FTINC@ -DSOURCE_PATH_SIZE=@SOURCE_PATH_SIZE@
lib_LTLIBRARIES = libfreetype-gl.la
libfreetype_gl_la_SOURCES = texture-atlas.c texture-font.c vector.c utf8-utils.c distance-field.c edtaa3func.c freetype-gl-err.c
include_HEADERS = freetype-gl.h vec234.h vector.h texture-atlas.h texture-font.h opengl.h distance-field.h edtaa3func.h freetype-gl-err.h freetype-gl-errdef.h
libfreetype_gl_la_LIBADD = -lm -l@LIBGL@ -lfreetype -lz @LIBADD@
libfreetype_gl_la_LIBADD = -lm -lfreetype -lz @LIBADD@
distclean-am: clean-am distclean-compile distclean-hdr distclean-libtool distclean-tags
......
## ExampleLib Example: an example of using Automake to link with a library
AC_INIT([freetype-gl], [1.3], [bernd@net2o.de], [freetype-gl for Linux/Android],
[http://lonesock.net/soil.html])
AC_INIT([freetype-gl], [1.4], [bernd@net2o.de], [freetype-gl for Linux/Android],
[https://github.com/forthy42/freetype-gl])
AC_PREREQ([2.59])
AM_INIT_AUTOMAKE([1.10 -Wall no-define])
AC_CONFIG_MACRO_DIR([m4])
......@@ -13,10 +13,6 @@ LT_INIT
case $CC in
*android*)
LIBADD="-llog"
LIBGL=GLESv2
;;
*)
LIBGL=GL
;;
esac
......@@ -24,11 +20,10 @@ esac
FTINC=`eval $ac_compiler -E -Wp,-v conftest.$ac_ext 2>&1 | grep '^ ' | while read i; do test -f $i/freetype2/ft2build.h && echo -I$i/freetype2; done`
rm conftest.$ac_ext
SOURCE_PATH_SIZE=$(echo $PWD | wc -c)
SOURCE_PATH_SIZE=0 #$(echo $PWD | wc -c)
AC_SUBST(FTINC)
AC_SUBST(LIBADD)
AC_SUBST(LIBGL)
AC_SUBST(SOURCE_PATH_SIZE)
PRECC=${CC%gcc*}
......
......@@ -8,6 +8,7 @@
#include FT_STROKER_H
// #include FT_ADVANCES_H
#include FT_LCD_FILTER_H
#include FT_TRUETYPE_TABLES_H
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
......@@ -200,6 +201,7 @@ texture_font_init(texture_font_t *self)
self->kerning = 1;
self->filtering = 1;
self->scaletex = 1;
self->scale = 1.0;
// FT_LCD_FILTER_LIGHT is (0x00, 0x55, 0x56, 0x55, 0x00)
// FT_LCD_FILTER_DEFAULT is (0x10, 0x40, 0x70, 0x40, 0x10)
......@@ -249,6 +251,16 @@ texture_library_new()
return self;
}
// -------------------------------------------------- texture_is_color_font ---
int
texture_is_color_font( texture_font_t *self) {
static const uint32_t tag = FT_MAKE_TAG('C', 'B', 'D', 'T');
unsigned long length = 0;
FT_Load_Sfnt_Table(self->face, tag, 0, NULL, &length);
return length != 0;
}
// --------------------------------------------- texture_font_new_from_file ---
texture_font_t *
texture_font_new_from_file(texture_atlas_t *atlas, const float pt_size,
......@@ -381,7 +393,6 @@ texture_font_load_face( texture_font_t *self, float size )
}
break;
}
}
/* Select charmap */
error = FT_Select_Charmap(self->face, FT_ENCODING_UNICODE);
......@@ -391,6 +402,32 @@ texture_font_load_face( texture_font_t *self, float size )
goto cleanup_face;
}
if( texture_is_color_font( self ) ) {
/* Select best size */
if (self->face->num_fixed_sizes == 0) {
freetype_error( error, "FT_Error (%s:%d) : no fixed size in color font\n",
__FILENAME__, __LINE__);
goto cleanup_face;
}
int best_match = 0;
int diff = abs((int)size - self->face->available_sizes[0].width);
for (int i = 1; i < self->face->num_fixed_sizes; ++i) {
int ndiff = abs((int)size - self->face->available_sizes[i].width);
if (ndiff < diff) {
best_match = i;
diff = ndiff;
}
}
error = FT_Select_Size(self->face, best_match);
self->scale = self->size / self->face->available_sizes[best_match].width;
if(error) {
freetype_error( error, "FT_Error (%s:%d, code 0x%02x) : %s\n",
__FILENAME__, __LINE__, FT_Errors[error].code, FT_Errors[error].message);
goto cleanup_face;
}
} else {
/* Set char size */
error = FT_Set_Char_Size(self->face, (int)(size * HRES), 0, DPI * HRES, DPI);
......@@ -399,9 +436,10 @@ texture_font_load_face( texture_font_t *self, float size )
__FILENAME__, __LINE__, FT_Errors[error].code, FT_Errors[error].message);
goto cleanup_face;
}
}
/* Set transform matrix */
FT_Set_Transform(self->face, &matrix, NULL);
}
return 1;
......@@ -572,6 +610,11 @@ texture_font_load_glyph( texture_font_t * self,
}
}
if( self->atlas->depth == 4 )
{
flags |= FT_LOAD_COLOR;
}
error = FT_Load_Glyph( self->face, glyph_index, flags );
if( error )
{
......@@ -631,10 +674,17 @@ texture_font_load_glyph( texture_font_t * self,
goto cleanup_stroker;
}
if( self->atlas->depth == 1 )
switch( self->atlas->depth ) {
case 1:
error = FT_Glyph_To_Bitmap( &ft_glyph, FT_RENDER_MODE_NORMAL, 0, 1);
else
break;
case 3:
error = FT_Glyph_To_Bitmap( &ft_glyph, FT_RENDER_MODE_LCD, 0, 1);
break;
case 4:
error = FT_Glyph_To_Bitmap( &ft_glyph, FT_RENDER_MODE_NORMAL, 0, 1);
break;
}
if( error )
{
......@@ -671,7 +721,7 @@ cleanup_stroker:
padding.left = 1;
}
size_t src_w = ft_bitmap.width/self->atlas->depth;
size_t src_w = ft_bitmap.width;
size_t src_h = ft_bitmap.rows;
size_t tgt_w = src_w + padding.left + padding.right;
......@@ -692,14 +742,15 @@ cleanup_stroker:
x = region.x;
y = region.y;
unsigned char *buffer = calloc( tgt_w * tgt_h * self->atlas->depth, sizeof(unsigned char) );
unsigned char *buffer = calloc( tgt_w * tgt_h, self->atlas->depth * sizeof(unsigned char) );
unsigned char *dst_ptr = buffer + (padding.top * tgt_w + padding.left) * self->atlas->depth;
unsigned char *src_ptr = ft_bitmap.buffer;
assert( self->atlas->depth == (ft_bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 1) );
for( i = 0; i < src_h; i++ )
{
//difference between width and pitch: https://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#FT_Bitmap
memcpy( dst_ptr, src_ptr, ft_bitmap.width);
memcpy( dst_ptr, src_ptr, ft_bitmap.width * self->atlas->depth);
dst_ptr += tgt_w * self->atlas->depth;
src_ptr += ft_bitmap.pitch;
}
......@@ -718,12 +769,12 @@ cleanup_stroker:
glyph = texture_glyph_new( );
glyph->codepoint = glyph_index ? utf8_to_utf32( codepoint ) : 0;
;
glyph->width = tgt_w;
glyph->height = tgt_h;
glyph->width = tgt_w * self->scale;
glyph->height = tgt_h * self->scale;
glyph->rendermode = self->rendermode;
glyph->outline_thickness = self->outline_thickness;
glyph->offset_x = ft_glyph_left;
glyph->offset_y = ft_glyph_top;
glyph->offset_x = ft_glyph_left * self->scale;
glyph->offset_y = ft_glyph_top * self->scale;
if(self->scaletex) {
glyph->s0 = x/(float)self->atlas->width;
glyph->t0 = y/(float)self->atlas->height;
......@@ -736,14 +787,22 @@ cleanup_stroker:
// half a pixel each to get crisp rendering
glyph->s0 = x - 0.5;
glyph->t0 = y - 0.5;
glyph->s1 = x + glyph->width - 0.5;
glyph->t1 = y + glyph->height - 0.5;
glyph->s1 = x + tgt_w - 0.5;
glyph->t1 = y + tgt_h - 0.5;
}
// Discard hinting to get advance
FT_Load_Glyph( self->face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);
FT_Load_Glyph( self->face, glyph_index,
((self->atlas->depth == 4) ? FT_LOAD_COLOR : 0) |
FT_LOAD_RENDER | FT_LOAD_NO_HINTING);
slot = self->face->glyph;
if( self->atlas->depth == 4 ) {
// color fonts use actual pixels, not subpixels
glyph->advance_x = slot->advance.x * self->scale;
glyph->advance_y = slot->advance.y * self->scale;
} else {
glyph->advance_x = slot->advance.x / HRESf;
glyph->advance_y = slot->advance.y / HRESf;
}
texture_font_index_glyph(self, glyph, ucodepoint);
if(!glyph_index) {
......
......@@ -376,6 +376,11 @@ typedef struct texture_font_t
* Whether to scale texture coordinates
*/
int scaletex;
/**
* factor to scale font coordinates
*/
float scale;
} texture_font_t;
/**
......@@ -397,7 +402,7 @@ typedef struct texture_font_t
* texture atlas is used to store glyph on demand. Note the depth of the atlas
* will determine if the font is rendered as alpha channel only (depth = 1) or
* RGB (depth = 3) that correspond to subpixel rendering (if available on your
* freetype implementation).
* freetype implementation), or RGBA (depth = 4) for color fonts.
*
* @param atlas A texture atlas
* @param pt_size Size of font to be created (in points)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment