The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

overview_glyph.c in libbirdfont

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdfont/overview_glyph.c.
Fix a bug in fallback font rendering with cairo
1 /* 2 Copyright (C) 2015 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 #include <assert.h> 16 #include <glib.h> 17 #include <stdio.h> 18 #include <cairo.h> 19 #include <cairo-ft.h> 20 #include <stdlib.h> 21 #include <ft2build.h> 22 #include FT_FREETYPE_H 23 #include FT_GLYPH_H 24 25 FT_Library freetype_library = NULL; 26 27 gboolean draw_overview_glyph (cairo_t* context, const char* font_file, gdouble width, gdouble height, gunichar character) { 28 FT_Face face; 29 int error; 30 gdouble units_per_em; 31 gdouble units; 32 gdouble advance; 33 int gid; 34 35 // private use area 36 if (0xe000 <= character && character <= 0xf8ff) { 37 return FALSE; 38 } 39 40 // control characters 41 if (character <= 0x001f || (0x007f <= character && character <= 0x008d)) { 42 return FALSE; 43 } 44 45 gchar text[7]; 46 int length = g_unichar_to_utf8 (character, text); 47 text[length] = '\0'; 48 49 if (freetype_library == NULL) { 50 error = FT_Init_FreeType (&freetype_library); 51 if (error) { 52 g_warning ("Freetype init error %d.\n", error); 53 return FALSE; 54 } 55 } 56 57 error = FT_New_Face (freetype_library, font_file, 0, &face); 58 if (error) { 59 g_warning ("Freetype font face error %d\n", error); 60 return FALSE; 61 } 62 63 units_per_em = face->units_per_EM; 64 units = (height * 0.5) / units_per_em; 65 66 error = FT_Select_Charmap (face , FT_ENCODING_UNICODE); 67 if (error) { 68 g_warning ("Freetype can not use Unicode, error: %d\n", error); 69 FT_Done_Face (face); 70 return FALSE; 71 } 72 73 error = FT_Set_Char_Size (face, 0, 64, (int) height, (int) height); 74 if (error) { 75 g_warning ("FT_Set_Char_Size, error: %d.\n", error); 76 FT_Done_Face (face); 77 return FALSE; 78 } 79 80 error = FT_Set_Pixel_Sizes (face, 0, (int) (height * 0.5)); 81 if (error) { 82 g_warning ("FT_Set_Pixel_Sizes, error: %d.\n", error); 83 FT_Done_Face (face); 84 return FALSE; 85 } 86 87 gid = FT_Get_Char_Index (face, character); 88 advance = 0; 89 if (gid != 0) { 90 FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE); 91 advance = face->glyph->metrics.horiAdvance; 92 advance *= units; 93 } else { 94 FT_Done_Face (face); 95 return FALSE; 96 } 97 98 static const cairo_user_data_key_t key; 99 100 cairo_save (context); 101 102 cairo_font_face_t* cairo_face = cairo_ft_font_face_create_for_ft_face (face, 0); 103 104 if (cairo_face == NULL) { 105 g_warning("cairo font face is null"); 106 FT_Done_Face (face); 107 return FALSE; 108 } 109 110 int status = cairo_font_face_set_user_data (cairo_face, &key, face, (cairo_destroy_func_t) FT_Done_Face); 111 112 if (status != CAIRO_STATUS_SUCCESS) { 113 cairo_font_face_destroy (cairo_face); 114 FT_Done_Face (face); 115 return FALSE; 116 } 117 118 cairo_set_font_face (context, cairo_face); 119 cairo_set_font_size (context, height * 0.5); 120 121 gdouble x = (width - advance) / 2; 122 123 if (x < 0) { 124 x = 0; 125 } 126 127 cairo_move_to (context, x, height - 30); 128 cairo_show_text (context, text); 129 130 cairo_font_face_destroy (cairo_face); 131 cairo_restore (context); 132 133 // cairo closes the font face and the library must be kept open 134 135 return TRUE; 136 } 137