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 <stdlib.h> 20 #include <ft2build.h> 21 #include FT_FREETYPE_H 22 #include FT_GLYPH_H 23 24 gboolean draw_overview_glyph (cairo_t* context, const char* font_file, gdouble width, gdouble height, gunichar character) { 25 FT_Library library; 26 FT_Face face; 27 int error; 28 FT_Glyph glyph; 29 FT_UInt glyph_index; 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 error = FT_Init_FreeType (&library); 46 if (error) { 47 g_warning ("Freetype init error %d.\n", error); 48 return FALSE; 49 } 50 51 error = FT_New_Face (library, font_file, 0, &face); 52 if (error) { 53 FT_Done_FreeType (library); 54 g_warning ("Freetype font face error %d\n", error); 55 return FALSE; 56 } 57 58 units_per_em = face->units_per_EM; 59 units = (height * 0.5) / units_per_em; 60 61 error = FT_Select_Charmap (face , FT_ENCODING_UNICODE); 62 if (error) { 63 g_warning ("Freetype can not use Unicode, error: %d\n", error); 64 FT_Done_Face (face); 65 FT_Done_FreeType (library); 66 return FALSE; 67 } 68 69 error = FT_Set_Char_Size (face, 0, 64, (int) height, (int) height); 70 if (error) { 71 g_warning ("FT_Set_Char_Size, error: %d.\n", error); 72 FT_Done_Face (face); 73 FT_Done_FreeType (library); 74 return FALSE; 75 } 76 77 error = FT_Set_Pixel_Sizes (face, 0, (int) (height * 0.5)); 78 if (error) { 79 g_warning ("FT_Set_Pixel_Sizes, error: %d.\n", error); 80 FT_Done_Face (face); 81 FT_Done_FreeType (library); 82 return FALSE; 83 } 84 85 gchar text[7]; 86 int length = g_unichar_to_utf8 (character, text); 87 text[length] = '\0'; 88 89 gid = FT_Get_Char_Index (face, character); 90 advance = 0; 91 if (gid != 0) { 92 FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE); 93 advance = face->glyph->metrics.horiAdvance; 94 advance *= units; 95 } else { 96 FT_Done_Face (face); 97 FT_Done_FreeType (library); 98 return FALSE; 99 } 100 101 cairo_save (context); 102 cairo_font_face_t* cairo_face = cairo_ft_font_face_create_for_ft_face (face, 0); 103 104 cairo_set_font_face (context, cairo_face); 105 cairo_set_font_size (context, height * 0.5); 106 107 gdouble x = (width - advance) / 2; 108 109 if (x < 0) { 110 x = 0; 111 } 112 113 cairo_move_to (context, x, height - 30); 114 cairo_show_text (context, text); 115 116 cairo_font_face_destroy (cairo_face); 117 cairo_restore (context); 118 119 FT_Done_Face (face); 120 FT_Done_FreeType (library); 121 122 return TRUE; 123 } 124