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;
--- 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 ();
}