Clone in a terminal:
Commit f58bce9
Johan Mattsson - 2015-12-18T16:48:26+00:00
f58bce95af53240229806c1135a0ecfc22db87b8johan.mattsson.m@gmail.com

Faster rendering of fallback fonts in the overview tab

Changed files (6)

Diff

diff --git a/libbirdfont/GlyphRange.vala b/libbirdfont/GlyphRange.valaindex c7e5bcd..5a97dcc 100644--- a/libbirdfont/GlyphRange.vala+++ b/libbirdfont/GlyphRange.vala@@ -28,7 +28,6 @@ public class GlyphRange { 	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,15 +430,9 @@ public class GlyphRange { 	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 @@ public class GlyphRange { 		} 		 		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 @@ public class GlyphRange { 		}  		 		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'; 		} 		diff --git a/libbirdfont/MainWindow.vala b/libbirdfont/MainWindow.valaindex 988069c..7b851a3 100644--- a/libbirdfont/MainWindow.vala+++ b/libbirdfont/MainWindow.vala@@ -170,7 +170,6 @@ public class MainWindow : GLib.Object { 
 	public void set_native (NativeWindow nw) {
 		native_window = nw;
-		OverViewItem.start_thumbnail_processing ();
 	}
 	 
 	public static FontDisplay get_current_display () {
diff --git a/libbirdfont/OverView.vala b/libbirdfont/OverView.valaindex c5f9195..1cda11c 100644--- a/libbirdfont/OverView.vala+++ b/libbirdfont/OverView.vala@@ -531,21 +531,13 @@ public class OverView : FontDisplay { 		int item_list_length; 		int visible_size; 		-		Test test = new Test.time("update_item_list");-		 		tab_with = allocation.width - 30; // scrollbar 		 		items_per_row = get_items_per_row (); 		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 @@ public class OverView : FontDisplay { 				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 @@ public class OverView : FontDisplay { 			} 		} 		-		warning (test_b.get_test_time ());-		-		warning (test3.get_test_time ());-		warning (test.get_test_time ()); 		update_scheduled = false; 	} 	diff --git a/libbirdfont/OverViewItem.vala b/libbirdfont/OverViewItem.valaindex e6dbada..20ff667 100644--- a/libbirdfont/OverViewItem.vala+++ b/libbirdfont/OverViewItem.vala@@ -15,6 +15,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 { 	 public class OverViewItem : GLib.Object {@@ -57,16 +60,6 @@ public class OverViewItem : GLib.Object {  	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 @@ public class OverViewItem : GLib.Object { 			}); 		}	 -/*-		thumbnail_mutex.lock ();-		if (!is_null (thumbnail_queue)) {-			thumbnail_queue.offer (this);-			has_thumnail_task.signal ();-		}-		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;+		info = new CharacterInfo (character, glyphs); 		-		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 ();-			}+		if (glyphs == null) {+			label = new Text ();+		} else {+			label = new Text ((!) character.to_string (), 17);		+			truncate_label (); 		}+		+		draw_background (); 	}  	public void draw_glyph_from_font () {@@ -209,6 +166,13 @@ public class OverViewItem : GLib.Object { 			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 @@ public class OverViewItem : GLib.Object { 			gx = (width - fallback.get_extent ()) / 2.0; 			gy = height - 30; 			fallback.draw_at_baseline (c, gx, gy);+			*/ 			c.restore (); 			 			cache = s;diff --git a/libbirdfont/Renderer/Text.vala b/libbirdfont/Renderer/Text.valaindex 1243fa8..dfd66ba 100644--- a/libbirdfont/Renderer/Text.vala+++ b/libbirdfont/Renderer/Text.vala@@ -260,7 +260,7 @@ public class Text : Widget { 			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; 			}diff --git a/libbirdfont/overview_glyph.c b/libbirdfont/overview_glyph.cnew file mode 100644index 0000000..03881d4--- /dev/null+++ b/libbirdfont/overview_glyph.c@@ -0,0 +1,113 @@+/*
+	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);
+}

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112