The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Faster rendering of fallback fonts in the overview tab

These changes was commited to the Birdfont repository Fri, 18 Dec 2015 16:43:09 +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>
Fri, 18 Dec 2015 16:43:09 +0000 (17:43 +0100)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Fri, 18 Dec 2015 16:48:26 +0000 (17:48 +0100)
commit f58bce95af53240229806c1135a0ecfc22db87b8
tree 717e33c965b1620888458ea731bde8daee2ddae6
parent 8928962902af44e60817e531d67f8e01d81ee45f
Faster rendering of fallback fonts in the overview tab

libbirdfont/GlyphRange.vala
libbirdfont/MainWindow.vala
libbirdfont/OverView.vala
libbirdfont/OverViewItem.vala
libbirdfont/Renderer/Text.vala
libbirdfont/overview_glyph.c [new ]
--- a/libbirdfont/GlyphRange.vala +++ b/libbirdfont/GlyphRange.vala @@ -28,7 +28,6 @@ bool range_is_class = false; uint32* range_index = null; int index_size = 0; - int index_hint = 0; public GlyphRange () { ranges = new Gee.ArrayList<UniRange> (); @@ -431,14 +430,8 @@ private void get_unirange_index (uint32 index, out UniRange? range, out uint32 range_start_index) { int lower = 0; int upper = index_size - 1; - int i; + int i = (lower + upper) / 2; int end = index_size - 1; - - if (index_hint >= 0 && index_hint < index_size) { - i = index_hint; - } else { - i = (lower + upper) / 2; - } range_start_index = -1; range = null; @@ -448,22 +441,20 @@ } while (true) { - if (i == end) { + if (i == end && range_index[i] <= index) { range_start_index = range_index[i]; range = ranges.get (i); - index_hint = i; break; - } else if (range_index[i] <= index && range_index[i + 1] > index) { + } else if (i != end && range_index[i] <= index && range_index[i + 1] > index) { range_start_index = range_index[i]; range = ranges.get (i); - index_hint = i; break; } if (lower >= upper) { break; } - + if (range_index[i] < index) { lower = i + 1; } else { @@ -512,7 +503,7 @@ } if (unlikely (range_start_index > index || range_start_index == -1)) { - warning ("Index out of bounds in glyph range."); + warning (@"Index out of bounds in glyph range, range_start_index: $range_start_index index: $index"); return '\0'; }
--- a/libbirdfont/MainWindow.vala +++ b/libbirdfont/MainWindow.vala @@ -170,7 +170,6 @@ public void set_native (NativeWindow nw) { native_window = nw; - OverViewItem.start_thumbnail_processing (); } public static FontDisplay get_current_display () {
--- a/libbirdfont/OverView.vala +++ b/libbirdfont/OverView.vala @@ -530,8 +530,6 @@ double tab_with; int item_list_length; int visible_size; - - Test test = new Test.time("update_item_list"); tab_with = allocation.width - 30; // scrollbar @@ -539,13 +537,7 @@ rows = (int) (allocation.height / OverViewItem.full_height ()) + 2; item_list_length = items_per_row * rows; - - foreach (OverViewItem overview_item in visible_items) { - overview_item.cancel_thumbnail_rendering (); - } - visible_items.clear (); - Test test3 = new Test.time("two conditions"); index = (uint32) first_visible; x = OverViewItem.margin; @@ -563,46 +555,44 @@ character = glyph.unichar_code; item = new OverViewItem (); - item.set_glyphs (glyphs); item.set_character (character); + item.set_glyphs (glyphs); item.x = x; item.y = y; visible_items.add (item); index++; } } else { - - Test test_mk = new Test.time("mk items"); uint32 glyph_range_size = glyph_range.get_length (); + + uint max_length = glyph_range.length () - first_visible; + + if (item_list_length > max_length) { + item_list_length = (int) max_length; + } for (int i = 0; i < item_list_length && index < glyph_range_size; i++) { item = new OverViewItem (); visible_items.add (item); } - warning (test_mk.get_test_time ()); - Test test_gl = new Test.time("get_glyph"); + index = (uint32) first_visible; visible_size = visible_items.size; for (int i = 0; i < visible_size; i++) { item = visible_items.get (i); - glyphs = f.get_glyph_collection_by_name ((!) item.character.to_string ()); - item.set_glyphs (glyphs); + character = glyph_range.get_character ((uint32) index); + item.set_character (character); + index++; } - warning (test_gl.get_test_time ()); - Test test_a = new Test.time("get_char"); - visible_size = visible_items.size; for (int i = 0; i < visible_size; i++) { item = visible_items.get (i); - character = glyph_range.get_character ((uint32) index); - item.set_character (character); - index++; + glyphs = f.get_glyph_collection_by_name ((!) item.character.to_string ()); + item.set_glyphs (glyphs); } - warning (test_a.get_test_time ()); } - Test test_b = new Test.time("adjust pos"); x = OverViewItem.margin; y = OverViewItem.margin; @@ -637,10 +627,6 @@ } } - warning (test_b.get_test_time ()); - - warning (test3.get_test_time ()); - warning (test.get_test_time ()); update_scheduled = false; }
--- a/libbirdfont/OverViewItem.vala +++ b/libbirdfont/OverViewItem.vala @@ -14,6 +14,9 @@ using Cairo; using Math; + + [CCode (cname = "draw_overview_glyph")] + public extern void draw_overview_glyph (Context context, string font_file, double width, double height, unichar character); namespace BirdFont { @@ -57,16 +60,6 @@ public void set_character (unichar character) { this.character = character; - info = new CharacterInfo (character, glyphs); - - if (glyphs == null) { - label = new Text (); - } else { - label = new Text ((!) character.to_string (), 17); - truncate_label (); - } - - draw_background (); } public void set_glyphs (GlyphCollection? gc) { @@ -86,52 +79,16 @@ }); } - /* - thumbnail_mutex.lock (); - if (!is_null (thumbnail_queue)) { - thumbnail_queue.offer (this); - has_thumnail_task.signal (); + info = new CharacterInfo (character, glyphs); + + if (glyphs == null) { + label = new Text (); + } else { + label = new Text ((!) character.to_string (), 17); + truncate_label (); } - thumbnail_mutex.unlock (); - */ - } - - public static void start_thumbnail_processing () { - //thumbnail_task = new Task (process_thumbnails, true); - thumbnail_queue = new Gee.PriorityQueue<OverViewItem> (); - //MainWindow.native_window.run_non_blocking_background_thread (thumbnail_task); - } - - public void cancel_thumbnail_rendering () { - thumbnail_mutex.lock (); - cancel_thumbnail = true; - thumbnail_mutex.unlock (); - } - - private static void process_thumbnails () { - bool cancel = false; - while (!thumbnail_task.is_cancelled ()) { - OverViewItem item; - - thumbnail_mutex.lock (); - item = thumbnail_queue.poll (); - thumbnail_mutex.unlock (); - - if (!is_null (item)) { - thumbnail_mutex.lock (); - cancel = item.cancel_thumbnail; - thumbnail_mutex.unlock (); - - if (!cancel) { - item.draw_background (); - } - } else { - thumbnail_mutex.lock (); - has_thumnail_task.wait (thumbnail_mutex); - thumbnail_mutex.unlock (); - } - } + draw_background (); } public void draw_glyph_from_font () { @@ -209,6 +166,13 @@ c.scale (Screen.get_scale (), Screen.get_scale ()); c.save (); + + string? font_file = find_font (FallbackFont.font_config, (!) character.to_string ()); + if (font_file != null) { + draw_overview_glyph (c, (!) font_file, width, height, character); + } + + /* Text fallback = new Text (); fallback.set_use_cache (false); Theme.text_color (fallback, "Overview Glyph"); @@ -218,6 +182,7 @@ gx = (width - fallback.get_extent ()) / 2.0; gy = height - 30; fallback.draw_at_baseline (c, gx, gy); + */ c.restore (); cache = s;
--- a/libbirdfont/Renderer/Text.vala +++ b/libbirdfont/Renderer/Text.vala @@ -260,7 +260,7 @@ double h; glyph.boundaries (out x1, out y1, out x2, out y2); h = Math.fmax (y1, y2) - Math.fmin (y1, y2); - h *= get_scale(glyph) - glyph.baseline * get_scale(glyph); + h *= get_scale (glyph) - glyph.baseline * get_scale (glyph); if (h > max_height) { max_height = h; }
--- /dev/null +++ b/libbirdfont/overview_glyph.c @@ -1,1 +1,114 @@ + /* + 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. + */ + + #include <assert.h> + #include <glib.h> + #include <stdio.h> + #include <cairo.h> + #include <stdlib.h> + #include <ft2build.h> + #include FT_FREETYPE_H + #include FT_GLYPH_H + + void draw_overview_glyph (cairo_t* context, const char* font_file, gdouble width, gdouble height, gunichar character) { + FT_Library library; + FT_Face face; + int error; + FT_Glyph glyph; + FT_UInt glyph_index; + gdouble units_per_em; + gdouble units; + gdouble advance; + int gid; + + // private use area + if (0xe000 <= character && character <= 0xf8ff) { + return; + } + + // control characters + if (character <= 0x001f || (0x007f <= character && character <= 0x008d)) { + return; + } + + error = FT_Init_FreeType (&library); + if (error) { + g_warning ("Freetype init error %d.\n", error); + return; + } + + error = FT_New_Face (library, font_file, 0, &face); + if (error) { + g_warning ("Freetype font face error %d\n", error); + return; + } + + units_per_em = face->units_per_EM; + units = (height * 0.7) / units_per_em; + + error = FT_Select_Charmap (face , FT_ENCODING_UNICODE); + if (error) { + g_warning ("Freetype can not use Unicode, error: %d\n", error); + return; + } + + error = FT_Set_Char_Size (face, 0, 64, (int) height, (int) height); + if (error) { + g_warning ("FT_Set_Char_Size, error: %d.\n", error); + return; + } + + error = FT_Set_Pixel_Sizes (face, 0, (int) (height * 0.5)); + if (error) { + g_warning ("FT_Set_Pixel_Sizes, error: %d.\n", error); + return; + } + + gchar text[7]; + int length = g_unichar_to_utf8 (character, text); + text[length] = '\0'; + + gid = FT_Get_Char_Index (face, character); + advance = 0; + if (gid != 0) { + FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE); + advance = face->glyph->metrics.horiAdvance; + advance *= units; + } else { + g_warning("Glyph not found: %s", text); + return; + } + + cairo_save (context); + cairo_font_face_t* cairo_face = cairo_ft_font_face_create_for_ft_face (face, 0); + + cairo_set_font_face (context, cairo_face); + cairo_set_font_size (context, height); + + gdouble x = (width - advance) / 2; + + if (x < 0) { + x = 0; + } + + cairo_move_to (context, x, height - 30); + cairo_show_text (context, text); + + cairo_font_face_destroy (cairo_face); + cairo_restore (context); + + FT_Done_Face (face); + FT_Done_FreeType (library); + }