The Birdfont Source Code


All Repositories / birdfont.git / commitdiff – RSS feed

Load fallback font data from a list of TTF fonts

These changes was commited to the Birdfont repository Thu, 21 May 2015 17:56:26 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
[Thu, 21 May 2015 17:56:26 +0000]

Updated Files

libbirdfont/BackgroundSelectionTool.vala
libbirdfont/BirdFontFile.vala
libbirdfont/FallbackFont.vala
libbirdfont/Font.vala
libbirdfont/Glyph.vala
libbirdfont/KerningDisplay.vala
libbirdfont/OpenFontFormat/OpenFontFormatReader.vala
libbirdfont/OpenFontFormat/load_font.c
libbirdfont/OverView.vala
libbirdfont/OverViewItem.vala
libbirdfont/Renderer/FallbackFont.vala
libbirdfont/Renderer/FontCache.vala
libbirdfont/Renderer/Text.vala
libbirdfont/Renderer/TextArea.vala
--- a/libbirdfont/BackgroundSelectionTool.vala +++ b/libbirdfont/BackgroundSelectionTool.vala @@ -66,15 +66,13 @@ cr.fill (); if (bs.assigned_glyph != null) { - if (label.has_character ((!) bs.assigned_glyph)) { - font_height = 18; - label.set_text ((!) bs.assigned_glyph); - label.set_font_size (font_height); - tx = x + w - label.get_width () / 2.0; - ty = y + h + label.get_acender () / 2.0 - label.get_decender (); - label.set_font_size (font_height); - label.draw_at_baseline (cr, tx, ty); - } + font_height = 18; + label.set_text ((!) bs.assigned_glyph); + label.set_font_size (font_height); + tx = x + w - label.get_width () / 2.0; + ty = y + h + label.get_acender () / 2.0 - label.get_decender (); + label.set_font_size (font_height); + label.draw_at_baseline (cr, tx, ty); } cr.restore ();
--- a/libbirdfont/BirdFontFile.vala +++ b/libbirdfont/BirdFontFile.vala @@ -49,7 +49,7 @@ return ok; } - + public bool load_part (string bfp_file) { string xml_data; XmlParser parser;
diff --git libbirdfont/FallbackFont.vala(deleted)
--- a/libbirdfont/FallbackFont.vala +++ /dev/null @@ -1,256 +1,1 @@ - /* - Copyright (C) 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 - published by the Free Software Foundation; either version 3 of the - License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - */ - - 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 () { - return SearchPaths.find_file (null, "fallback-font.sqlite"); - } - - public File get_new_database_file () { - string? fn = BirdFont.get_argument ("--fallback-font"); - - if (fn != null && ((!) fn) != "") { - return File.new_for_path ((!) fn); - } - - return File.new_for_path ("fallback-font.sqlite"); - } - - public void generate_fallback_font () { - File f = get_new_database_file (); - string? fonts = BirdFont.get_argument ("--fonts"); - string fallback; - - if (fonts == null) { - stderr.printf ("Add a list of fonts to use as fallback to the \"--fonts\" argument.\n"); - stderr.printf ("Separate each font file with \":\"\n"); - return; - } - - fallback = (!) fonts; - - stdout.printf ("Generating fallback font: %s\n", (!) f.get_path ()); - - try { - if (f.query_exists ()) { - f.delete (); - } - - open_database (f); - create_tables (); - - foreach (string font in fallback.split (":")) { - add_font (font); - } - } catch (GLib.Error e) { - warning (e.message); - } - - } - - /* //FIXME:DELETE - public void add_font (string font_file) { - Font font; - Glyph g; - BirdFontFile bf; - File single_glyph_font; - - font = new Font (); - single_glyph_font = File.new_for_path ("/tmp/fallback_glyph.bf"); - - font.set_file (font_file); - if (!font.load ()) { - stderr.printf ("Failed to load font: " + font_file); - return; - } - - for (int i = 0; i < font.length (); i++) { - 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); - - db = (!) database; - - if (rc != Sqlite.OK) { - stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ()); - } - } - - public void create_tables () { - int ec; - string? errmsg; - string create_font_table = """ - CREATE TABLE FallbackFont ( - unicode INTEGER PRIMARY KEY NOT NULL, - font_data TEXT NOT NULL - ); - """; - - ec = db.exec (create_font_table, null, out errmsg); - if (ec != Sqlite.OK) { - warning ("Error: %s\n", (!) errmsg); - } - } - } - - }
--- a/libbirdfont/Font.vala +++ b/libbirdfont/Font.vala @@ -451,7 +451,7 @@ } } - public string get_name_for_character (unichar c) { + public static string get_name_for_character (unichar c) { StringBuilder sb; if (c == 0) {
--- a/libbirdfont/Glyph.vala +++ b/libbirdfont/Glyph.vala @@ -1962,7 +1962,7 @@ last_name = glyph.name; for (int i = pos + 1; i < glyph_sequence.char_count (); i++) { c = glyph_sequence.get_char (i); - name = font.get_name_for_character (c); + name = (!) c.to_string (); juxtaposed = (font.has_glyph (name)) ? (!) font.get_glyph (name) : font.get_space ().get_current (); if (font.has_glyph (last_name) && font.has_glyph (name)) { @@ -1995,7 +1995,7 @@ last_name = glyph.name; for (int i = pos - 1; i >= 0; i--) { c = glyph_sequence.get_char (i); - name = font.get_name_for_character (c); + name = (!) c.to_string (); juxtaposed = (font.has_glyph (name)) ? (!) font.get_glyph (name) : font.get_space ().get_current (); if (font.has_glyph (last_name) && font.has_glyph (name)) {
--- a/libbirdfont/KerningDisplay.vala +++ b/libbirdfont/KerningDisplay.vala @@ -696,7 +696,7 @@ f = current_font; if (!is_modifier_key (c) && c.validate ()) { - name = f.get_name_for_character (c); + name = (!) c.to_string (); g = f.get_glyph_by_name (name); inser_glyph (g); }
--- a/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala +++ b/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala @@ -27,10 +27,10 @@ public extern static StringBuilder? load_glyph (FontFace font, uint unicode); [CCode (cname = "open_font")] - public extern static FontFace open_font (string font_file); + public extern static FontFace* open_font (string font_file); - [CCode (cname = "close_font")] - public extern static FontFace close_font (FontFace font); + [CCode (cname = "close_ft_font")] + public extern static void close_font (FontFace* font); namespace BirdFont {
--- a/libbirdfont/OpenFontFormat/load_font.c +++ b/libbirdfont/OpenFontFormat/load_font.c @@ -524,7 +524,7 @@ } g_string_append (bf, contour->str); - g_string_free (contour, 0); + g_string_free (contour, TRUE); } free (new_points); @@ -541,7 +541,7 @@ int i; int start; int end; - + if (face->glyph->outline.n_points == 0) { return bf; } @@ -551,7 +551,7 @@ end = face->glyph->outline.contours [i]; contour = get_bf_contour_data (unicode, face->glyph->outline.points + start, face->glyph->outline.tags + start, end - start, units_per_em, err); g_string_append_printf (bf, "\t\t<path data=\"%s\" />\n", contour->str); - g_string_free (contour, 0); + g_string_free (contour, TRUE); start = face->glyph->outline.contours [i] + 1; } @@ -559,38 +559,57 @@ } FontFace* open_font (const char* file) { - FT_Library library; - FT_Face face; + FT_Library library = NULL; + FT_Face face = NULL; int error; FontFace* font; error = FT_Init_FreeType (&library); if (error != OK) { - g_warning ("Freetype init error %d.\n", error); + printf ("Freetype init error %d.\n", error); return NULL; } error = FT_New_Face (library, file, 0, &face); if (error) { + if (FT_Done_FreeType (library) != 0) { + g_warning ("Can't close freetype."); + } + g_warning ("Freetype font face error %d\n", error); return NULL; } - + + font = malloc (sizeof (FontFace)); + font->face = face; + font->library = library; + error = FT_Select_Charmap (face , FT_ENCODING_UNICODE); if (error) { g_warning ("Freetype can not use Unicode, error: %d\n", error); + close_ft_font (font); return NULL; } - font = malloc (sizeof (FontFace)); - font->face = face; - font->library = library; + return font; } - void close_font (FontFace* font) { + void close_ft_font (FontFace* font) { if (font != NULL) { - FT_Done_Face (font->face); - FT_Done_FreeType (font->library); + if (font->face != NULL) { + if (FT_Done_Face (font->face) != 0) { + g_warning ("Can't close font."); + } + font->face = NULL; + } + + if (font->library != NULL) { + if (FT_Done_FreeType (font->library) != 0) { + g_warning ("Can't close freetype."); + } + font->library = NULL; + } + free (font); } } @@ -602,9 +621,12 @@ int gid; FT_ULong charcode = (FT_ULong) unicode; double units; + gchar line_position_buffer[80]; + gchar* line_position = (gchar*) &line_position_buffer; + FT_Error error; - if (font == NULL || font->face == NULL) { - g_warning ("No font in load_glyph"); + if (font == NULL || font->face == NULL || font->library == NULL) { + printf ("WARNING No font in load_glyph"); return NULL; } @@ -614,24 +636,49 @@ return NULL; } - glyph = g_string_new (""); - FT_Load_Glyph(font->face, gid, FT_LOAD_DEFAULT | FT_LOAD_NO_SCALE); + units = get_units (font->face->units_per_EM); - paths = get_bf_path (unicode, font->face, font->face->units_per_EM, &err); - - if (err != OK) { - g_warning ("WARNING Can't load glyph."); + glyph = g_string_new ("<font>"); + + g_string_append_printf (glyph, "<horizontal>\n"); + + g_ascii_formatd (line_position, 80, "%f", font->face->ascender * units); + g_string_append_printf (glyph, "\t<top_limit>%s</top_limit>\n", line_position); + + g_string_append_printf (glyph, "\t<base_line>0</base_line>\n"); + + g_ascii_formatd (line_position, 80, "%f", font->face->descender * units); + g_string_append_printf (glyph, "\t<bottom_limit>%s</bottom_limit>\n", line_position); + + g_string_append_printf (glyph, "</horizontal>\n"); + + error = FT_Load_Glyph(font->face, gid, FT_LOAD_DEFAULT | FT_LOAD_NO_SCALE); + + if (error != 0) { + printf ("WARNING Failed to load glyph."); + g_string_free (glyph, TRUE); + return NULL; } - units = get_units (font->face->units_per_EM); + paths = get_bf_path (unicode, font->face, font->face->units_per_EM, &err); + if (err != OK) { + printf ("WARNING Can't load glyph."); + g_string_free (glyph, TRUE); + g_string_free (paths, TRUE); + return NULL; + } + + g_string_append_printf (glyph, "<collection unicode=\"U+%x\">\n", (guint)charcode); 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_append_printf (glyph, "%s", "\t</collection>"); + g_string_append_printf (glyph, "%s", "</font>"); - g_string_free (paths, 0); + g_string_free (paths, TRUE); if (err != OK) { g_warning ("Can't load glyph data."); @@ -878,7 +925,7 @@ } g_string_append (bf, glyph->str); - g_string_free (glyph, 0); + g_string_free (glyph, TRUE); } bird_font_open_font_format_reader_append_kerning (bf, file);
--- a/libbirdfont/OverView.vala +++ b/libbirdfont/OverView.vala @@ -52,15 +52,9 @@ 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 @@ -164,8 +164,6 @@ double glyph_width, glyph_height; Surface s; Context c; - Text fallback; - double font_size; OverView o; Color color = Color.black (); @@ -182,7 +180,7 @@ g = ((!) gl).get_current (); } else { o = MainWindow.get_overview (); - g = o.fallback_font.get_glyph (character); + g = FontCache.fallback_font.get_glyph (character); color = Theme.get_color ("Overview Glyph"); }
--- /dev/null +++ b/libbirdfont/Renderer/FallbackFont.vala @@ -1,1 +1,257 @@ + /* + Copyright (C) 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 + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + */ + + using Gee; + using Sqlite; + using Bird; + + namespace BirdFont { + + public class FallbackFont : GLib.Object { + static unowned Database db; + static Database? database = null; + + Gee.ArrayList<File> fallback_fonts; + Gee.ArrayList<File> font_directories; + + public FallbackFont () { + string home = Environment.get_home_dir (); + + fallback_fonts = new Gee.ArrayList<File> (); + 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"); + + //FIXME: MAC + + open_fallback_fonts (); + } + + void open_fallback_fonts () { + add_font ("times.ttf"); + add_font ("arial.ttf"); + add_font ("verdana.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 ()) { + 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) { + return get_glyph_from_ttf (c); + } + + public Glyph get_glyph_from_ttf (unichar c) { + Glyph? g = null; + File f; + FontFace* font; + + for (int i = fallback_fonts.size - 1; i >= 0; i--) { + f = fallback_fonts.get (i); + + font = open_font ((!) f.get_path ()); + + if (font != null) { + g = get_glyph_in_font ((!) font, c); + } + + close_font (font); + + if (g != null) { + return (!) g; + } + } + + return new Glyph (""); + } + + public Glyph? get_glyph_in_font (FontFace font, unichar c) { + StringBuilder? glyph_data = null; + GlyphCollection gc; + BirdFontFile bf_parser; + Font bf_font; + + gc = new GlyphCollection (c, (!)c.to_string ()); + glyph_data = load_glyph (font, (uint) c); + + if (glyph_data == null) { + return null; + } + + bf_font = new Font (); + bf_parser = new BirdFontFile (bf_font); + bf_parser.load_data (((!) glyph_data).str); + + return bf_font.get_glyph_by_name ((!) c.to_string ()); + } + + public File get_database_file () { + return SearchPaths.find_file (null, "fallback-font.sqlite"); + } + + public File get_new_database_file () { + string? fn = BirdFont.get_argument ("--fallback-font"); + + if (fn != null && ((!) fn) != "") { + return File.new_for_path ((!) fn); + } + + return File.new_for_path ("fallback-font.sqlite"); + } + + public void generate_fallback_font () { + File f = get_new_database_file (); + string? fonts = BirdFont.get_argument ("--fonts"); + string fallback; + + if (fonts == null) { + stderr.printf ("Add a list of fonts to use as fallback to the \"--fonts\" argument.\n"); + stderr.printf ("Separate each font file with \":\"\n"); + return; + } + + fallback = (!) fonts; + + stdout.printf ("Generating fallback font: %s\n", (!) f.get_path ()); + + try { + if (f.query_exists ()) { + f.delete (); + } + + open_database (f); + create_tables (); + + foreach (string font in fallback.split (":")) { + add_font (font); + } + } catch (GLib.Error e) { + warning (e.message); + } + + } + + /* //FIXME:DELETE + public void add_font (string font_file) { + Font font; + Glyph g; + BirdFontFile bf; + File single_glyph_font; + + font = new Font (); + single_glyph_font = File.new_for_path ("/tmp/fallback_glyph.bf"); + + font.set_file (font_file); + if (!font.load ()) { + stderr.printf ("Failed to load font: " + font_file); + return; + } + + for (int i = 0; i < font.length (); i++) { + 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); + + db = (!) database; + + if (rc != Sqlite.OK) { + stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ()); + } + } + + public void create_tables () { + int ec; + string? errmsg; + string create_font_table = """ + CREATE TABLE FallbackFont ( + unicode INTEGER PRIMARY KEY NOT NULL, + font_data TEXT NOT NULL + ); + """; + + ec = db.exec (create_font_table, null, out errmsg); + if (ec != Sqlite.OK) { + warning ("Error: %s\n", (!) errmsg); + } + } + } + + }
--- a/libbirdfont/Renderer/FontCache.vala +++ b/libbirdfont/Renderer/FontCache.vala @@ -18,32 +18,38 @@ /** Thread specific font cache. */ public class FontCache { + public static FallbackFont fallback_font; + static FontCache? default_cache = null; Gee.HashMap<string, Font> fonts; public FontCache () { fonts = new Gee.HashMap<string, Font> (); + + if (is_null (fallback_font)) { + fallback_font = new FallbackFont (); + } } public void reload_font (string file_name) { - Font? f = get_font (file_name); + Font? f = get_font (file_name).font; if (f != null) { ((!) f).load (); } } - public Font? get_font (string file_name) { + public CachedFont get_font (string file_name) { Font f; bool ok; if (file_name == "") { stderr.printf ("No file name.\n"); - return null; + return new CachedFont (null); } if (fonts.has_key (file_name)) { - return fonts.get (file_name); + return new CachedFont (fonts.get (file_name)); } f = new Font (); @@ -51,12 +57,12 @@ ok = f.load (); if (!ok) { stderr.printf ("Can't load %s\n", file_name); - return null; + return new CachedFont (null); } fonts.set (file_name, f); - return f; + return new CachedFont (f); } public static FontCache get_default_cache () { @@ -65,8 +71,51 @@ } return (!) default_cache; + } + + public CachedFont get_fallback () { + return new CachedFont (null); + } + + public class CachedFont : GLib.Object { + public Font? font; + + // FIXME: move fallback glyphs in to fond boundaries + public double top_limit = 84; + public double base_line = 0; + public double bottom_limit = -27; + + public CachedFont (Font? font) { + this.font = font; + } + + public Glyph? get_glyph_by_name (string name) { + Glyph? g = null; + + if (font != null) { + g = ((!) font).get_glyph_by_name (name); + } + + if (g == null && name.char_count () == 1) { + g = fallback_font.get_glyph (name.get_char (0)); + } + + return g; + } + + public GlyphCollection get_not_def_character () { + Font f; + + if (font != null) { + return ((!) font).get_not_def_character (); + } + + f = new Font (); + + return f.get_not_def_character (); + } } } }
--- a/libbirdfont/Renderer/Text.vala +++ b/libbirdfont/Renderer/Text.vala @@ -15,30 +15,12 @@ using Cairo; namespace BirdFont { - + /** Test implementation of a birdfont rendering engine. */ public class Text : Widget { - - public Font font { - get { - if (current_font == null) { - current_font = get_default_font (); - - if (current_font == null) { - current_font = new Font (); - } - } - - return (!) current_font; - } - - set { - current_font = value; - } - } + FontCache font_cache; + public FontCache.CachedFont cached_font; - FontCache font_cache; - Font? current_font; public string text; GlyphSequence glyph_sequence { @@ -51,6 +33,7 @@ } } + Gee.ArrayList<string> glyph_names; GlyphSequence? gs = null; public delegate void Iterator (Glyph glyph, double kerning, bool last); @@ -66,9 +49,9 @@ double truncated_width = -1; public Text (string text = "", double size = 17, double margin_bottom = 0) { - current_font = null; this.margin_bottom = margin_bottom; font_cache = FontCache.get_default_cache (); + cached_font = font_cache.get_fallback (); set_font_size (size); set_text (text); @@ -76,12 +59,6 @@ public void use_cache (bool cache) { use_cached_glyphs = cache; - } - - public static void load_default_font () { - if (get_default_font () == null) { - warning ("Default font not found."); - } } /** Set font for this text area. @@ -95,15 +72,11 @@ f = File.new_for_path (font_file); path = (f.query_exists ()) ? f : SearchPaths.find_file (null, font_file); - current_font = FontCache.get_default_cache ().get_font ((!) path.get_path ()); - return current_font != null; + cached_font = FontCache.get_default_cache ().get_font ((!) path.get_path ()); + + return cached_font.font != null; } - - public static Font? get_default_font () { - File path = SearchPaths.find_file (null, "roboto.bf"); - return FontCache.get_default_cache ().get_font ((!) path.get_path ()); - } - + public void set_font_size (double height_in_pixels) { font_size = height_in_pixels; sidebearing_extent = 0; @@ -128,19 +101,16 @@ gs = new GlyphSequence (); + glyph_names = new Gee.ArrayList<string> (); index = 0; while (text.get_next_char (ref index, out c)) { - name = font.get_name_for_character (c); - g = font.get_glyph_by_name (name); + name = (!) c.to_string (); + g = cached_font.get_glyph_by_name (name); gs.glyph.add (g); + glyph_names.add (name); } return gs; - } - - /** @param character a string with a single glyph or the name of the glyph if it is a ligature. */ - public bool has_character (string character) { - return font.has_glyph (character); } public void iterate (Iterator iter) { @@ -162,13 +132,22 @@ word = glyph_sequence; wi = 0; - - return_if_fail (current_font != null); - word_with_ligatures = word.process_ligatures ((!) current_font); + + if (cached_font.font != null) { + word_with_ligatures = word.process_ligatures ((!) cached_font.font); + } else { + word_with_ligatures = word.process_ligatures (new Font ()); + } gr_left = null; gr_right = null; - kc = ((!) current_font).get_kerning_classes (); + + if (cached_font.font != null) { + kc = ((!) cached_font.font).get_kerning_classes (); + } else { + kc = new KerningClasses (new Font ()); + } + for (int i = 0; i < word_with_ligatures.glyph.size; i++) { g = word_with_ligatures.glyph.get (i); @@ -186,7 +165,11 @@ } // process glyph - glyph = (g == null) ? font.get_not_def_character ().get_current () : (!) g; + if (g == null) { + g = cached_font.get_glyph_by_name (glyph_names.get (i)); + } + + glyph = (g == null) ? cached_font.get_not_def_character ().get_current () : (!) g; iter (glyph, kern, i + 1 == word_with_ligatures.glyph.size); prev = g; @@ -259,7 +242,7 @@ } }); - return max_height * ratio - font.base_line * ratio; + return max_height * ratio - cached_font.base_line * ratio; } public override double get_width () { @@ -303,18 +286,18 @@ } }); - decender = font.base_line * ratio - min_y * ratio; + decender = cached_font.base_line * ratio - min_y * ratio; return decender > 0 ? decender : 0; } public override void draw (Context cr) { - double y = widget_y + get_height () + get_scale () * (font.bottom_limit + font.base_line); + double y = widget_y + get_height () + get_scale () * (cached_font.bottom_limit + cached_font.base_line); draw_at_baseline (cr, widget_x, y); } public void draw_at_top (Context cr, double px, double py, string cacheid = "") { double s = get_scale (); - double y = py + s * (font.top_limit - font.base_line); + double y = py + s * (cached_font.top_limit - cached_font.base_line); draw_at_baseline (cr, px, y, cacheid); } @@ -346,7 +329,7 @@ double cc_y; ratio = get_scale (); - cc_y = (font.top_limit - font.base_line) * ratio; + cc_y = (cached_font.top_limit - cached_font.base_line) * ratio; y = py; x = px; @@ -463,7 +446,7 @@ ya = y - prev.y * scale; cr.move_to (xa, ya); - by = (y - font.base_line * scale); + by = (y - cached_font.base_line * scale); for (int i = 0; i < path.points.size; i++) { e = path.points.get (i).copy (); PenTool.convert_point_segment_type (prev, e, PointType.CUBIC); @@ -486,11 +469,11 @@ } public double get_baseline_to_bottom () { - return get_scale () * (-font.base_line - font.bottom_limit); + return get_scale () * (-cached_font.base_line - cached_font.bottom_limit); } public double get_scale () { - return font_size / (font.top_limit - font.bottom_limit); + return font_size / (cached_font.top_limit - cached_font.bottom_limit); } public void truncate (double max_width) {
--- a/libbirdfont/Renderer/TextArea.vala +++ b/libbirdfont/Renderer/TextArea.vala @@ -1110,7 +1110,7 @@ } if (paint_background && !(partial_start || partial_stop)) { - double selection_y = widget_y + next_word.widget_y + scale * -next_word.font.bottom_limit - font_size; + double selection_y = widget_y + next_word.widget_y + scale * -next_word.cached_font.bottom_limit - font_size; cr.rectangle (widget_x + padding + next_word.widget_x - 1, selection_y, cw + 1, font_size); cr.fill (); } @@ -1129,7 +1129,7 @@ cwi = (glyph.get_width ()) * next_word.get_scale () + kerning; if (draw) { - double selection_y = widget_y + next_word.widget_y + scale * -next_word.font.bottom_limit - font_size; + double selection_y = widget_y + next_word.widget_y + scale * -next_word.cached_font.bottom_limit - font_size; cr.rectangle (bx - 1, selection_y, cwi + 1, font_size); cr.fill (); }