Segmentation Fault when loading font with FreeType
I'm trying to use the FreeType library together with libpng to output a PNG image of a glyph. My code compiles just fine but I then run into a segmentation fault. Here's some debugging output from gdb (I'm not sure what to make of it):
(gdb) run
Starting program: /home/david/Desktop/a.out
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff76a58a5 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) where
#0 0x00007ffff76a58a5 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff7bcb298 in png_write_row (png_ptr=0x611320, row=<optimized out>)
at /usr/include/x86_64-linux-gnu/bits/string3.h:52
#2 0x00007ffff7bcb56c in png_write_image (png_ptr=0x611320, image=0x60d218)
at pngwrite.c:608
#3 0x0000000000400c35 in main ()
And here's the code:
#include <stdlib.h>
#include <stdio.h>
#include <png.h>
#include <ft2build.h>
#include FT_FREETYPE_H
main() {
// Declare FreeType variables
FT_Library library;
FT_Face face;
FT_GlyphSlot slot;
FT_UInt glyph_index = 30;
char* font_file = "/usr/share/fonts/truetype/freefont/FreeMono.ttf";
// Declare PNG variables
png_uint_32 width = 100;
png_uint_32 height = 100;
int bit_depth = 16;
int color_type = PNG_COLOR_TYPE_GRAY;
char* file_name = "/home/david/Desktop/out.png";
png_structp png_ptr;
png_infop info_ptr;
// Render font
int error;
error = FT_Init_FreeType(&library);
error = FT_New_Face(library, font_file, 0, &face);
error = FT_Set_Pixel_Sizes(face, 100, 100);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
if (error) {
printf("ERROR CODE: %d", error);
}
// Create a PNG file
FILE *fp = fopen(file_name, "wb");
// Create the PNG in memory
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
info_ptr = png_create_info_struct(png_ptr);
png_init_io(png_ptr, fp);
// Write the header
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info(png_ptr, info_ptr);
// Write image data
slot = face->glyph;
png_write_image(png_ptr, &slot->bitmap.buffer);
// End write
png_write_end(png_ptr, NULL);
fclose(fp);
}
UPDATE
I'm trying a slightly new approach (using png_write_row instead of png_write_image).
... SAME AS BEFORE ABOVE ....
// Write image data
slot = face->glyph;
int x, y, offset;
for (y = 0; y < slot->bitmap.rows; y++) {
for (x = 0; x < slot->bitmap.width; x++) {
offset = y*(slot->bitmap.width) + x;
png_write_row(png_ptr, &slot->bitmap.buffer[offset]);
}
}
// End write
png_write_end(png_ptr, NULL);
fclose(fp);
}
Now I get some more useful libpng errors, but I'm still not sure what to make of them:
libpng warning: zstream not in use (internal error)
libpng error: stream error
Aborted (core dumped)
Two suggestions:
Take a look for all compiler warnings in order to see that the pointers types match properly.
-
Trace the possible errors better. For example write something like this:
int error; error = FT_Init_FreeType(&library); if (error) { printf("ERROR CODE: %d", error); } error = FT_New_Face(library, font_file, 0, &face); if (error) { printf("ERROR CODE: %d", error); } error = FT_Set_Pixel_Sizes(face, 100, 100); if (error) { printf("ERROR CODE: %d", error); } error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); if (error) { printf("ERROR CODE: %d", error); } error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); if (error) { printf("ERROR CODE: %d", error); }
Any error on one of this calls may cause a misplaced pointer that may trigger the segmentation fault.
This can be obvious:
FILE *fp = fopen(file_name, "wb");
if ( fp == null ) {
printf ("Unable to open file for writing"):
}
But if for example you are attempting to write your file in a directory without the permissions, you will have fp pointing to NULL and the further segmentation fault.