Loading Makefile.am +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading configure.ac +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]) Loading @@ -13,10 +13,6 @@ LT_INIT case $CC in *android*) LIBADD="-llog" LIBGL=GLESv2 ;; *) LIBGL=GL ;; esac Loading @@ -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*} Loading texture-font.c +94 −35 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) Loading Loading @@ -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, Loading Loading @@ -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); Loading @@ -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); Loading @@ -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; Loading Loading @@ -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 ) { Loading Loading @@ -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 ) { Loading Loading @@ -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; Loading @@ -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; } Loading @@ -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; Loading @@ -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) { Loading texture-font.h +6 −1 Original line number Diff line number Diff line Loading @@ -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; /** Loading @@ -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) Loading Loading
Makefile.am +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
configure.ac +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]) Loading @@ -13,10 +13,6 @@ LT_INIT case $CC in *android*) LIBADD="-llog" LIBGL=GLESv2 ;; *) LIBGL=GL ;; esac Loading @@ -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*} Loading
texture-font.c +94 −35 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) Loading Loading @@ -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, Loading Loading @@ -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); Loading @@ -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); Loading @@ -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; Loading Loading @@ -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 ) { Loading Loading @@ -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 ) { Loading Loading @@ -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; Loading @@ -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; } Loading @@ -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; Loading @@ -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) { Loading
texture-font.h +6 −1 Original line number Diff line number Diff line Loading @@ -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; /** Loading @@ -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) Loading