Commit 9e7fb91
Fallback font
Changed files (7)
modifiedlibbirdfont/BirdFontFile.valamodifiedlibbirdfont/FallbackFont.valamodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/OpenFontFormat/OpenFontFormatReader.valamodifiedlibbirdfont/OpenFontFormat/load_font.cmodifiedlibbirdfont/OverView.valamodifiedlibbirdfont/OverViewItem.vala
Diff
@@ -1163,7 +1163,7 @@ class BirdFontFile : GLib.Object { 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;@@ -14,6 +14,7 @@ using Gee; using Sqlite;+using Bird; namespace BirdFont { @@ -21,7 +22,139 @@ 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 @@ public class FallbackFont : GLib.Object { } +/* //FIXME:DELETE public void add_font (string font_file) { Font font; Glyph g;@@ -89,7 +223,7 @@ public class FallbackFont : GLib.Object { 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);@@ -1497,17 +1497,18 @@ public class Glyph : FontDisplay { } /** 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 ();@@ -12,12 +12,26 @@ 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 { [SimpleType]@@ -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 @@ -34,6 +34,11 @@ #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) { return 100.0 / units_per_em;@@ -513,7 +518,7 @@ GString* get_bf_contour_data (guint unicode, FT_Vector* points, char* flags, int 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++; }@@ -553,6 +558,88 @@ GString* get_bf_path (guint unicode, FT_Face face, double units_per_em, int* err 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. * @gid glyph id * @return character code@@ -680,9 +767,6 @@ GString* get_bf_font (FT_Face face, char* file, int* err) { } 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));@@ -53,9 +53,15 @@ public class OverView : FontDisplay { 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 (); set_glyph_range (gr);@@ -166,6 +166,8 @@ public class OverViewItem : GLib.Object { Context c; Text fallback; double font_size;+ OverView o;+ Color color = Color.black (); font = BirdFont.get_current_font (); w = width;@@ -178,37 +180,30 @@ public class OverViewItem : GLib.Object { 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 ();