[cairo] Possible bug/misuse in set_scaled_font/set_font_face & FreeType
Jeremy Moles
cubicool at gmail.com
Mon Dec 16 11:06:00 PST 2013
(This is a resubmission; my intial post was rejected because I attached
a huge font file, sorry.)
Hello all! I am developing a (pretty cool) 2D text scenegraph library
that uses Cairo, Harfbuzz, and glyphy. While working on some of the core
components, I think I have discovered a bug (or perhaps more likely, a
misuse) in/of Cairo. Attached is a very simple demo application.
You'll notice that I only use FreeType to load the initial font file,
and then quickly create a cairo_font_fact_t* from that directly. I never
call FT_Set_Char_Size, nor do I want to manage the font size with
FreeType directly.
The issue I've found is that unless I call:
cairo_get_scaled_font()
...after a call to cairo_set_font_size(), then the font glyphs seem to
have wrong/null origins. I know that that the implementation is probably
calling FT_Set_Char_Size underneath the hood, but it doesn't seem to
actually "apply" until after the get_scaled_font() call. I don't know
how else to best describe it, so I just attached a really simple example
demonstrating it.
Hopefully I can get some advice/comments on my usage.
Thanks!
-------------- next part --------------
#include <stdlib.h>
#include <stdio.h>
#include <ft2build.h>
#include <harfbuzz/hb.h>
#include <harfbuzz/hb-ft.h>
#include <harfbuzz/hb-icu.h>
#include <cairo/cairo.h>
#include <cairo/cairo-ft.h>
int main(int argc, char** argv) {
FT_Library ft_library;
FT_Face ft_face;
hb_font_t* hb_font;
hb_buffer_t* buf;
hb_glyph_info_t* glyph_info;
hb_glyph_position_t* glyph_pos;
cairo_font_face_t* cr_font;
cairo_surface_t* surface;
cairo_t* cr;
cairo_glyph_t* cairo_glyphs;
unsigned int i;
unsigned int glyph_count;
int x = 50;
int y = 90;
FT_Init_FreeType(&ft_library);
FT_New_Face(ft_library, "DejaVuSerif.ttf", 0, &ft_face);
hb_font = hb_ft_font_create(ft_face, NULL);
cr_font = cairo_ft_font_face_create_for_ft_face(ft_face, 0);
surface = cairo_image_surface_create(
CAIRO_FORMAT_RGB24,
512,
128
);
cr = cairo_create(surface);
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
cairo_set_font_face(cr, cr_font);
cairo_set_font_size(cr, 50.0);
/* The "bug" is here. Without this call, the new glyphs don't have proper "origins"
* it seems. I wish my terminology was better. */
cairo_get_scaled_font(cr);
buf = hb_buffer_create();
hb_buffer_set_unicode_funcs(buf, hb_icu_get_unicode_funcs());
hb_buffer_set_direction(buf, HB_DIRECTION_LTR);
hb_buffer_set_script(buf, HB_SCRIPT_LATIN);
hb_buffer_set_language(buf, hb_language_from_string("en", strlen("en")));
hb_buffer_add_utf8(buf, "FOOBARBAZ", 9, 0, 9);
hb_shape(hb_font, buf, NULL, 0);
glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count);
glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
cairo_glyphs = malloc(sizeof(cairo_glyph_t) * glyph_count);
for(i = 0; i < glyph_count; i++) {
cairo_glyphs[i].index = glyph_info[i].codepoint;
cairo_glyphs[i].x = x + (glyph_pos[i].x_offset / 64);
cairo_glyphs[i].y = y - (glyph_pos[i].y_offset / 64);
x += glyph_pos[i].x_advance / 64;
y -= glyph_pos[i].y_advance / 64;
}
cairo_show_glyphs(cr, cairo_glyphs, glyph_count);
cairo_surface_write_to_png(surface, "foo.png");
free(cairo_glyphs);
hb_buffer_destroy(buf);
hb_font_destroy(hb_font);
cairo_surface_destroy(surface);
cairo_destroy(cr);
FT_Done_FreeType(ft_library);
return 0;
}
-------------- next part --------------
CC = gcc
CFLAGS = -g -O2 -Wall --pedantic `freetype-config --cflags` `pkg-config --cflags harfbuzz-icu` -W -Wall -Wno-unused-parameter
LDFLAGS =`icu-config --ldflags`
LIBS = -lcairo -lharfbuzz `freetype-config --libs` `pkg-config --libs harfbuzz-icu`
main: main.c
$(CC) $(<) $(CFLAGS) -o $(@) $(LDFLAGS) $(LIBS)
clean:
rm -f main
More information about the cairo
mailing list