Possible bug/misuse in set_scaled_font/set_font_face & FreeType

Jeremy Moles <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
(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!

-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
main.c (text/plain, 2.3 KB)
#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;
}
Makefile (text/plain, 345 B)
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.