Loading a font from a file to pango?
Asked Answered
P

2

6

I have a code uses Cairo and Pango to create an image :

#include<stdio.h>
#include<cairo.h>
#include<pango/pangocairo.h>

#define IMAGE_WIDTH  650
#define IMAGE_HEIGHT 150

#define TEXT "HELLO WORLD"
#define FONT "MizuFontAlphabet Normal 40"

/*
 * $ gcc $(pkg-config pangocairo cairo --cflags --libs) file.c
 */


int main(int argc , char** argv) {

    cairo_surface_t *surface;
    cairo_t *cr;

    PangoLayout *layout;
    PangoFontDescription *desc;
    PangoRectangle extents;

    surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, IMAGE_WIDTH, IMAGE_HEIGHT);
    cr      = cairo_create(surface);

    cairo_rectangle(cr, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_fill(cr);
    cairo_stroke(cr);

    /* the font is needed to be installed in fonts directory */
    layout  = pango_cairo_create_layout(cr);
    pango_layout_set_text(layout, TEXT, -1);
    desc    = pango_font_description_from_string(FONT);
    pango_layout_set_font_description(layout, desc);
    pango_font_description_free (desc);

    pango_layout_get_pixel_extents(layout, NULL, &extents);
    int x   = (int) (IMAGE_WIDTH - extents.width) / 2;
    int y   = (int) (IMAGE_HEIGHT - extents.height) / 2;

    cairo_set_source_rgb(cr, 0.33, 0.55, 0.88);
    cairo_move_to(cr, x, y);
    pango_cairo_show_layout(cr, layout);

    g_object_unref(layout);

    cairo_surface_write_to_png(surface, "image.png");

    cairo_destroy(cr);
    cairo_surface_destroy(surface);

    return(0);
}

The font I use , MizuFontAlphabet, is a none-standard font so it is needed to be installed in the fonts directory so I can use it with Pango :

    desc    = pango_font_description_from_string(FONT);

How could I load the font from a file in case that font wasn't installed?

Phrixus answered 23/5, 2012 at 14:56 Comment(0)
F
7

This problem can be solved fairly easily by adding a custom font to the local fontconfig state:

#include <fontconfig/fontconfig.h>


std::string yourFontFilePath = "/home/testUser/bla.ttf";
const FcChar8 * file = (const FcChar8 *)yourFontFilePath.c_str();
FcBool fontAddStatus = FcConfigAppFontAddFile(FcConfigGetCurrent(), file);

Now the pango rendering engine will use your custom font just by using the PangoFontDescription.

Femininity answered 31/8, 2015 at 12:35 Comment(6)
change FcConfigAppFOntAddFile to FcConfigAppFontAddFileCordes
This answer assumes pango is using a fontconfig backend. Do you know of a cross-platform solution that works at the pango level?Columella
How do I create a PangoFontDescription that refers to the given bla.ttf font?Aschim
@Aschim any luck finding a solution?Cease
I just called pango_font_description_new() . This is the relevant code: PangoFontDescription* desc = pango_font_description_new(); pango_font_description_set_absolute_size(desc,(int)(textsize * PANGO_SCALE)/10); PangoLayout* layout = pango_cairo_create_layout (cr); if (eval_markup) pango_layout_set_markup_with_accel (layout, text,-1,'_', NULL); else pango_layout_set_text (layout, text,-1); pango_layout_set_font_description(layout,desc); pango_font_description_free(desc);Aschim
However, I've changed from pango to 'fontdue' (I'm writing a rust-program, and a pure-rust font renderer is much more convenient).Aschim
A
1

You'll need Freetype to do that.

You may want to have a look at the following (GPL licensed) code from the fontview library.

Especially, the function font_model_new:

GObject *font_model_new (gchar *fontfile) {
    FontModel *model;
    FT_Library library;
    FT_Face face;
    FcConfig *config;
    TT_OS2* os2;

    g_return_val_if_fail (fontfile, NULL);

    if (FT_Init_FreeType(&library)) {
        g_error ("FT_Init_FreeType failed");
        return NULL;
    }

    if (FT_New_Face (library, fontfile, 0, &face)) {
        g_error ("FT_New_Face failed");
        return NULL;
    }

    if (!FT_IS_SFNT(face)) {
        g_error ("Not an SFNT font!");
        return NULL;
    }

    config = FcConfigCreate ();
    if (!FcConfigAppFontAddFile (config, (FcChar8*)fontfile)) {
        g_error ("FcConfigAppFontAddFile failed");
        return NULL;
    }

    model = g_object_new (FONT_MODEL_TYPE, NULL);
    model->file = g_strdup (fontfile);
    model->ft_face = face;
    model->config = config;
    model->family = face->family_name;
    model->style = face->style_name;
    model->units_per_em = face->units_per_EM;

    model->xheight = 0;
    model->ascender = 0;
    model->descender = 0;

    model->sample = NULL;

    memset(&model->color, 0, sizeof (ColorTable));

    /* Get font metadata if available/applicable */
    os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
    if (os2) {
        model->xheight = os2->sxHeight;
        model->ascender = os2->sTypoAscender;
        model->descender = os2->sTypoDescender;
    }

    model->family = get_font_name (face, TT_NAME_ID_PREFERRED_FAMILY);
    if (!model->family)
        model->family = get_font_name (face, TT_NAME_ID_FONT_FAMILY);

    model->style = get_font_name (face, TT_NAME_ID_PREFERRED_SUBFAMILY);
    if (!model->style)
        model->style = get_font_name (face, TT_NAME_ID_FONT_SUBFAMILY);

    model->copyright = get_font_name (face, TT_NAME_ID_COPYRIGHT);
    model->version = get_font_name (face, TT_NAME_ID_VERSION_STRING);
    model->description = get_font_name (face, TT_NAME_ID_DESCRIPTION);
    model->sample = get_font_name (face, TT_NAME_ID_SAMPLE_TEXT);

    model->mmvar = NULL;
    model->mmcoords = NULL;
    if (FT_HAS_MULTIPLE_MASTERS (face)) {
        if (FT_Get_MM_Var (face, &model->mmvar) != 0) {
            model->mmvar = NULL;
        }
    }

    load_color_table (model);

    return G_OBJECT (model);
}
Autodidact answered 1/6, 2012 at 7:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.