Verified Commit f16d5830 authored by Bernd Paysan's avatar Bernd Paysan
Browse files

Added support for color emoji fonts

parent 1a764f7e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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

+3 −8
Original line number Diff line number Diff line
## 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*}
+94 −35
Original line number Diff line number Diff line
@@ -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) {
+6 −1
Original line number Diff line number Diff line
@@ -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)