The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Fallback font

These changes was commited to the Birdfont repository Thu, 21 May 2015 09:48:41 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
author Johan Mattsson <johan.mattsson.m@gmail.com>
Thu, 21 May 2015 09:48:41 +0000 (11:48 +0200)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Thu, 21 May 2015 12:39:24 +0000 (14:39 +0200)
commit 9e7fb91684a9ab59493fb9fbf343ef235b113a71
tree 3c0e2764b132e74011a27475803a7de43309fa6f
parent 25037943b58f50963a5dc407e46876506801e761
Fallback font

libbirdfont/BirdFontFile.vala
libbirdfont/FallbackFont.vala
libbirdfont/Glyph.vala
libbirdfont/OpenFontFormat/OpenFontFormatReader.vala
libbirdfont/OpenFontFormat/load_font.c
libbirdfont/OverView.vala
libbirdfont/OverViewItem.vala
--- a/libbirdfont/BirdFontFile.vala +++ b/libbirdfont/BirdFontFile.vala @@ -1163,7 +1163,7 @@ return id; } - private void parse_glyph (Tag tag, GlyphCollection gc, string name, + public void parse_glyph (Tag tag, GlyphCollection gc, string name, unichar unicode, int selected_id, bool unassigned) { Glyph glyph = new Glyph (name, unicode); Path path;
--- a/libbirdfont/FallbackFont.vala +++ b/libbirdfont/FallbackFont.vala @@ -14,14 +14,147 @@ using Gee; using Sqlite; + using Bird; namespace BirdFont { public class FallbackFont : GLib.Object { static unowned Database db; static Database? database = null; + + Gee.ArrayList<FontFace> fallback_fonts; + Gee.ArrayList<File> font_directories; public FallbackFont () { + string home = Environment.get_home_dir (); + + fallback_fonts = new Gee.ArrayList<FontFace> (); + font_directories = new Gee.ArrayList<File> (); + + add_font_folder ("/usr/share/fonts/"); + add_font_folder ("/usr/local/share/fonts/"); + add_font_folder (home + "/.local/share/fonts"); + add_font_folder ("C:\\Windows\\Fonts"); + + open_fallback_fonts (); + } + + ~FallbackFont () { + foreach (FontFace f in fallback_fonts) { + close_font (f); + } + } + + void open_fallback_fonts () { + add_font ("times.ttf"); + add_font ("verdana.ttf"); + add_font ("arial.ttf"); + add_font ("calibri.ttf"); + + add_font ("Ubuntu-R.ttf"); + + add_font ("DroidKufi.ttf"); + add_font ("DroidSansGeorgian.ttf"); + add_font ("DroidSansHebrew.ttf"); + add_font ("DroidNaskh.ttf"); + add_font ("DroidSansJapanese.ttf"); + add_font ("DroidSansArabic.ttf"); + add_font ("DroidSansArmenian.ttf"); + add_font ("DroidSans.ttf"); + add_font ("DroidSansEthiopic.ttf"); + add_font ("DroidSansFallbackFull.ttf"); + + add_font ("Roboto-Regular.ttf"); + } + + void add_font (string font) { + File f = find_font_file (font); + + if (f.query_exists ()) { + add_font_file (f); + } + } + + void add_font_file (File font_file) { + FontFace f = open_font ((!) font_file.get_path ()); + fallback_fonts.add (f); + } + + File find_font_file (string font_file) { + File d, f; + + for (int i = font_directories.size - 1; i >= 0; i--) { + d = font_directories.get (i); + f = get_child (d, font_file); + + if (f.query_exists ()) { + return f; + } + } + + return File.new_for_path (font_file); + } + + void add_font_folder (string f) { + File folder = File.new_for_path (f); + FileInfo? file_info; + string fn; + + try { + if (folder.query_exists ()) { + font_directories.add (folder); + + var enumerator = folder.enumerate_children (FileAttribute.STANDARD_NAME + "," + FileAttribute.STANDARD_TYPE, 0); + + while ((file_info = enumerator.next_file ()) != null) { + fn = ((!) file_info).get_name (); + + if (((!)file_info).get_file_type () == FileType.DIRECTORY) { + add_font_folder ((!) get_child (folder, fn).get_path ()); + } + } + } + } catch (GLib.Error e) { + warning (e.message); + } + } + + public Glyph get_glyph (unichar c) { + Glyph? g; + FontFace f; + + for (int i = fallback_fonts.size - 1; i >= 0; i--) { + f = fallback_fonts.get (i); + g = get_glyph_in_font (f, c); + + if (g != null) { + return (!) g; + } + } + + return new Glyph (""); + } + + public Glyph? get_glyph_in_font (FontFace font, unichar c) { + StringBuilder? glyph_data; + GlyphCollection gc; + XmlParser parser; + BirdFontFile bf_parser; + + gc = new GlyphCollection (c, (!)c.to_string ()); + glyph_data = load_glyph (font, (uint) c); + + if (glyph_data == null) { + return null; + } + + parser = new XmlParser (((!) glyph_data).str); + bf_parser = new BirdFontFile (new Font ()); + + bf_parser.parse_glyph (parser.get_root_tag (), + gc, gc.get_name (), gc.get_unicode_character (), 0, false); + + return gc.get_current (); } public File get_database_file () { @@ -70,6 +203,7 @@ } + /* //FIXME:DELETE public void add_font (string font_file) { Font font; Glyph g; @@ -89,7 +223,7 @@ g = (!) font.get_glyph_indice (i); bf = new BirdFontFile (font); } - } + } */ public void open_database (File db_file) { int rc = Database.open ((!) db_file.get_path (), out database);
--- a/libbirdfont/Glyph.vala +++ b/libbirdfont/Glyph.vala @@ -1497,17 +1497,18 @@ } /** Draw filled paths. */ - public void draw_paths (Context cr) { + public void draw_paths (Context cr, Color? c = null) { PathList stroke; - + Color color = c == null ? Color.black () : (!) c; + cr.save (); cr.new_path (); foreach (Path p in path_list) { if (p.stroke > 0) { stroke = p.get_stroke_fast (); - draw_path_list (stroke, cr, Color.black ()); + draw_path_list (stroke, cr, color); } else { - p.draw_path (cr, this, Color.black ()); + p.draw_path (cr, this, color); } } cr.fill ();
--- a/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala +++ b/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala @@ -11,12 +11,26 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ + + [SimpleType] + [CCode (cname = "FontFace")] + public extern class FontFace { + } [CCode (cname = "load_freetype_font")] public extern static StringBuilder? load_freetype_font (string file, out int error); [CCode (cname = "validate_freetype_font")] public extern static bool validate_freetype_font (string file); + + [CCode (cname = "load_glyph")] + public extern static StringBuilder? load_glyph (FontFace font, uint unicode); + + [CCode (cname = "open_font")] + public extern static FontFace open_font (string font_file); + + [CCode (cname = "close_font")] + public extern static FontFace close_font (FontFace font); namespace BirdFont {
--- a/libbirdfont/OpenFontFormat/load_font.c +++ b/libbirdfont/OpenFontFormat/load_font.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 2014 Johan Mattsson + Copyright (C) 2013 2014 2015 Johan Mattsson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -33,6 +33,11 @@ #define CUBIC_CURVE 2 #define DOUBLE_CURVE 4 #define HIDDEN_CURVE 8 + + typedef struct FontFace { + FT_Face face; + FT_Library library; + } FontFace; /** Convert units per em in font file format to the BirdFont format. */ double get_units (double units_per_em) { @@ -513,7 +518,7 @@ i += 1; } else { contour = g_string_new (""); - g_warning ("WARNING Can not parse outline.\n"); + g_warning ("WARNING Can't parse outline.\n"); *err = 1; i++; } @@ -551,6 +556,88 @@ } return bf; + } + + FontFace* open_font (const char* file) { + FT_Library library; + FT_Face face; + int error; + FontFace* font; + + error = FT_Init_FreeType (&library); + if (error != OK) { + g_warning ("Freetype init error %d.\n", error); + return NULL; + } + + error = FT_New_Face (library, file, 0, &face); + if (error) { + g_warning ("Freetype font face error %d\n", error); + return NULL; + } + + error = FT_Select_Charmap (face , FT_ENCODING_UNICODE); + if (error) { + g_warning ("Freetype can not use Unicode, error: %d\n", error); + return NULL; + } + + font = malloc (sizeof (FontFace)); + font->face = face; + font->library = library; + } + + void close_font (FontFace* font) { + if (font != NULL) { + FT_Done_Face (font->face); + FT_Done_FreeType (font->library); + free (font); + } + } + + GString* load_glyph (FontFace* font, guint unicode) { + GString* glyph; + GString* paths; + int err = OK; + int gid; + FT_ULong charcode = (FT_ULong) unicode; + double units; + + if (font == NULL || font->face == NULL) { + g_warning ("No font in load_glyph"); + return NULL; + } + + gid = FT_Get_Char_Index (font->face, charcode); + + if (gid == 0) { + return NULL; + } + + glyph = g_string_new (""); + FT_Load_Glyph(font->face, gid, FT_LOAD_DEFAULT | FT_LOAD_NO_SCALE); + + paths = get_bf_path (unicode, font->face, font->face->units_per_EM, &err); + + if (err != OK) { + g_warning ("WARNING Can't load glyph."); + } + + units = get_units (font->face->units_per_EM); + + g_string_append_printf (glyph, "\t<glyph left=\"%f\" right=\"%f\" selected=\"true\">\n", + 0.0, font->face->glyph->metrics.horiAdvance * units); + + g_string_append_printf (glyph, "%s", paths->str); + g_string_append_printf (glyph, "%s", "\t</glyph>"); + + g_string_free (paths, 0); + + if (err != OK) { + g_warning ("Can't load glyph data."); + } + + return glyph; } /** Get char code for a glyph. @@ -680,9 +767,6 @@ } g_string_append (bf, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n"); - - // libxml2 fails on doctype declaration in windows. - g_string_append (bf, "<font>\n"); g_string_append_printf (bf, "<postscript_name>%s</postscript_name>\n", g_markup_escape_text (FT_Get_Postscript_Name(face), -1));
--- a/libbirdfont/OverView.vala +++ b/libbirdfont/OverView.vala @@ -52,9 +52,15 @@ CharacterInfo? character_info = null; double scroll_size = 1; + + public static FallbackFont fallback_font; public OverView (GlyphRange? range = null, bool open_selected = true) { GlyphRange gr; + + if (is_null (fallback_font)) { + fallback_font = new FallbackFont (); + } if (range == null) { gr = new GlyphRange ();
--- a/libbirdfont/OverViewItem.vala +++ b/libbirdfont/OverViewItem.vala @@ -166,6 +166,8 @@ Context c; Text fallback; double font_size; + OverView o; + Color color = Color.black (); font = BirdFont.get_current_font (); w = width; @@ -178,37 +180,30 @@ if (gl != null) { g = ((!) gl).get_current (); - g.boundaries (out x1, out y1, out x2, out y2); + } else { + o = MainWindow.get_overview (); + g = o.fallback_font.get_glyph (character); + color = Theme.get_color ("Overview Glyph"); + } - glyph_width = x2 - x1; - glyph_height = y2 - y1; - - gx = ((w / glyph_scale) - glyph_width) / 2; - gy = (h / glyph_scale) - 25 / glyph_scale; + g.boundaries (out x1, out y1, out x2, out y2); + + glyph_width = x2 - x1; + glyph_height = y2 - y1; + + gx = ((w / glyph_scale) - glyph_width) / 2; + gy = (h / glyph_scale) - 25 / glyph_scale; - c.save (); - c.scale (glyph_scale, glyph_scale); + c.save (); + c.scale (glyph_scale, glyph_scale); - g.add_help_lines (); - - c.translate (gx - g.get_lsb () - Glyph.xc (), g.get_baseline () + gy - Glyph.yc ()); - - g.draw_paths (c); - c.restore (); - } else { - c.save (); - fallback = new Text (); - Theme.text_color (fallback, "Overview Glyph"); - fallback.set_text ((!) character.to_string ()); - font_size = height * 0.8; - fallback.set_font_size (font_size); - gx = (width - fallback.get_extent ()) / 2.0; - gy = height - 30; - fallback.set_font_size (font_size); - fallback.draw_at_baseline (c, gx, gy); - c.restore (); - } - + g.add_help_lines (); + + c.translate (gx - g.get_lsb () - Glyph.xc (), g.get_baseline () + gy - Glyph.yc ()); + + g.draw_paths (c, color); + c.restore (); + cr.save (); cr.set_source_surface (s, x, y - h); cr.paint ();