Clone in a terminal:
Commit 8c9f498
Johan Mattsson - 2014-11-20T18:16:04+00:00
8c9f4984afb77d318bf298ceabfeaf8be4d49e02johan.mattsson.m@gmail.com

Speed optimizations for the font name tab

Changed files (15)

Diff

diff --git a/libbirdfont/CheckBox.vala b/libbirdfont/CheckBox.valaindex 5a23da3..276fc46 100644--- a/libbirdfont/CheckBox.vala+++ b/libbirdfont/CheckBox.vala@@ -61,6 +61,7 @@ public class CheckBox : Widget { 		 		cr.save (); 		cr.set_line_width (1);+		cr.set_source_rgba (0, 0, 0, 1);		 		draw_rounded_rectangle (cr, widget_x, widget_y + center_y, w, h - padding, padding); 		cr.stroke (); 		cr.restore ();@@ -68,6 +69,7 @@ public class CheckBox : Widget { 		if (checked) { 			cr.save (); 			+			cr.set_source_rgba (0, 0, 0, 1); 			cr.set_line_width (1); 			 			cr.move_to (widget_x + d, widget_y + d + center_y);diff --git a/libbirdfont/ClipTool.vala b/libbirdfont/ClipTool.valaindex 7b20ec3..70e2993 100644--- a/libbirdfont/ClipTool.vala+++ b/libbirdfont/ClipTool.vala@@ -31,7 +31,6 @@ public class ClipTool : Tool { 		string svg_data; 		string bf_data; 		string data;-		TextArea t; 		 		if (fd is Glyph) { 			svg_data = ExportTool.export_selected_paths_to_svg ();@@ -86,7 +85,6 @@ public class ClipTool : Tool { 		Glyph g = MainWindow.get_current_glyph (); 		double x, y, w, h; 		double dx, dy;-		TextArea t; 		 		if (fd is Glyph) { 			paste_paths (false);diff --git a/libbirdfont/DescriptionDisplay.vala b/libbirdfont/DescriptionDisplay.valaindex 0f371ed..7a3034c 100644--- a/libbirdfont/DescriptionDisplay.vala+++ b/libbirdfont/DescriptionDisplay.vala@@ -167,25 +167,31 @@ public class DescriptionDisplay : FontDisplay { 		cr.restore ();  		foreach (Widget w in widgets) {-			if (w is Text) {-				cr.save ();-				cr.set_source_rgba (0, 0, 0, 1);-				w.draw (cr);-				cr.restore ();-			} else {-				w.draw (cr);+			if (w.is_on_screen ()) {			+				if (w is Text) {+					cr.save ();+					cr.set_source_rgba (0, 0, 0, 1);+					w.draw (cr);+					cr.restore ();+				} else {+					w.draw (cr);+				} 			} 		} 	}	  	void layout () { 		double y = -scroll;-		double margin; 		 		foreach (Widget w in widgets) { 			w.widget_x = 17 * MainWindow.units; 			w.widget_y = y; 			w.allocation = allocation;+			+			if (w is TextArea) {+				((TextArea) w).layout ();+			}+			 			y += w.get_height () + w.margin_bottom; 		} 		diff --git a/libbirdfont/Expander.vala b/libbirdfont/Expander.valaindex 5cf1614..d7f6247 100644--- a/libbirdfont/Expander.vala+++ b/libbirdfont/Expander.vala@@ -232,7 +232,7 @@ public class Expander : GLib.Object { 			if (headline != null) { 				title = new Text (); 				title.set_text ((!) headline);-				cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+				title.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1); 				title.set_font_size (14); 				title.draw_at_baseline (cr, x, yt + HEADLINE_MARGIN + 7); 			} else if (draw_separator) {		diff --git a/libbirdfont/FontName.vala b/libbirdfont/FontName.valaindex ea80afb..0ac2945 100644--- a/libbirdfont/FontName.vala+++ b/libbirdfont/FontName.vala@@ -50,7 +50,7 @@ public class FontName : Tool { 			text_height *= max_width / extent; 		} 		-		cr.set_source_rgba (234 / 255.0, 77 / 255.0, 26 / 255.0, 1);+		font_name.set_source_rgba (234 / 255.0, 77 / 255.0, 26 / 255.0, 1); 		font_name.set_font_size (text_height); 		font_name.draw_at_baseline (cr, x, y + 13 * Toolbox.get_scale ()); 		cr.restore ();diff --git a/libbirdfont/Glyph.vala b/libbirdfont/Glyph.valaindex a961e1b..91a3d3e 100644--- a/libbirdfont/Glyph.vala+++ b/libbirdfont/Glyph.vala@@ -14,6 +14,7 @@  using Cairo; using Math;+using Gee;  namespace BirdFont { @@ -94,6 +95,10 @@ public class Glyph : FontDisplay { 	/** Cache quadratic form on export. */ 	GlyfData? ttf_data = null; 	+	/** Cache for Cairo rendering */+	+	HashMap<int64?, Surface> glyph_cache = new HashMap<int64?, Surface> ((Gee.HashDataFunc<int64?>) hash_int64,  (Gee.EqualDataFunc<int64?>) equal_int64);+ 	public Glyph (string name, unichar unichar_code = 0) { 		this.name = name; 		this.unichar_code = unichar_code;@@ -120,7 +125,7 @@ public class Glyph : FontDisplay { 		 		return (!) ttf_data; 	}-+	 	public PathList get_quadratic_paths () { 		PointConverter pc; 		PathList pl;@@ -2068,6 +2073,39 @@ public class Glyph : FontDisplay { 			} 		}	 	}++	public void set_cache (int64 font_size, Surface cache) {+		glyph_cache.set (font_size, cache);+	}++	public bool has_cache (int64 font_size) {+		return glyph_cache.has_key (font_size);+	}++	public Surface get_cache (int64 font_size) {+		if (unlikely (!has_cache (font_size))) {+			warning ("No cache for glyph.");+			return new ImageSurface (Cairo.Format.ARGB32, 1, 1);+		}+		+		return glyph_cache.get (font_size);+	}+	+	public static bool equal_int64 (int64? i1, int64? i2) {+		if (i1 == null || i1 == null) {+			return false;+		}+		+		return (!) i1 == (!) i2;+	}++	public static int hash_int64 (int64? i) {+		if (i == 0) {+			return 0;+		}+		+		return (int) (0xFFFFFFFF & i);+	} }  }diff --git a/libbirdfont/Headline.vala b/libbirdfont/Headline.valaindex 7537868..eb095fd 100644--- a/libbirdfont/Headline.vala+++ b/libbirdfont/Headline.vala@@ -34,7 +34,7 @@ class Headline : Widget { 		cr.restore (); 			 		cr.save ();-		cr.set_source_rgba (1, 1, 1, 1);+		label.set_source_rgba (1, 1, 1, 1); 		label.set_font_size (20 * MainWindow.units); 		label.draw_at_baseline (cr, 21 * MainWindow.units, widget_y + 25 * MainWindow.units); 		cr.restore ();diff --git a/libbirdfont/LabelTool.vala b/libbirdfont/LabelTool.valaindex 1eeb4b2..ca9f2d7 100644--- a/libbirdfont/LabelTool.vala+++ b/libbirdfont/LabelTool.vala@@ -68,9 +68,9 @@ public class LabelTool : Tool { 		text_height = 18;  		if (is_selected ()) {-			cr.set_source_rgba (1, 1, 1, 1);+			label_text.set_source_rgba (1, 1, 1, 1); 		} else {-			cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+			label_text.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1); 		} 		 		label_text.set_font_size (text_height);@@ -98,9 +98,9 @@ public class LabelTool : Tool { 			center_y = bgy + ((!) counter_background).get_height () / 2.0 + 4 / scale; 			 			if (is_selected ()) {-				cr.set_source_rgba (1, 1, 1, 1);+				glyph_count.set_source_rgba (1, 1, 1, 1); 			} else {-				cr.set_source_rgba (51 / 255.0, 54 / 255.0, 59 / 255.0, 1);+				glyph_count.set_source_rgba (51 / 255.0, 54 / 255.0, 59 / 255.0, 1); 			} 			 			glyph_count.set_font_size (text_height);diff --git a/libbirdfont/Menu.vala b/libbirdfont/Menu.valaindex c4e096d..4ed6f42 100644--- a/libbirdfont/Menu.vala+++ b/libbirdfont/Menu.vala@@ -573,7 +573,6 @@ public class Menu : GLib.Object { 	}  	public bool has_menu_item (string identifier) {-		int i = 0; 		foreach (MenuItem mi in sorted_menu_items) { 			if (mi.identifier == identifier) { 				return true;diff --git a/libbirdfont/OverViewItem.vala b/libbirdfont/OverViewItem.valaindex d28df9f..c2cb346 100644--- a/libbirdfont/OverViewItem.vala+++ b/libbirdfont/OverViewItem.vala@@ -114,7 +114,7 @@ public class OverViewItem : GLib.Object { 	}  	public void adjust_scale () {-		double x1, x2, y1, y2, glyph_width, glyph_height, scale, gx, gy;+		double x1, x2, y1, y2, glyph_width, glyph_height, scale, gx; 		Glyph g; 		Font font; 		@@ -184,7 +184,7 @@ public class OverViewItem : GLib.Object { 		} else { 			c.save (); 			fallback = new Text ();-			c.set_source_rgba (219 / 255.0, 221 / 255.0, 233 / 255.0, 1);+			fallback.set_source_rgba (219 / 255.0, 221 / 255.0, 233 / 255.0, 1); 			fallback.set_text ((!) character.to_string ()); 			font_size = height * 0.8; 			fallback.set_font_size (font_size);diff --git a/libbirdfont/Renderer/Text.vala b/libbirdfont/Renderer/Text.valaindex f8719f0..cb0a9d8 100644--- a/libbirdfont/Renderer/Text.vala+++ b/libbirdfont/Renderer/Text.vala@@ -43,7 +43,13 @@ public class Text : Widget { 	GlyphSequence glyph_sequence; 	public delegate void Iterator (Glyph glyph, double kerning, bool last); 	public double font_size;-	+	public double sidebearing_extent = 0;++	double r = 0;+	double g = 0;+	double b = 0;+	double a = 1;+			 	public Text (string text = "", double size = 17, double margin_bottom = 0) { 		current_font = null; 		this.margin_bottom = margin_bottom;@@ -56,6 +62,7 @@ public class Text : Widget {  	public void set_font_size (double height_in_pixels) { 		font_size = height_in_pixels;+		sidebearing_extent = 0; 	}  	public void set_font_cache (FontCache font_cache) {@@ -76,7 +83,7 @@ public class Text : Widget { 			name = font.get_name_for_character (c); 			g = font.get_glyph_by_name (name); 			glyph_sequence.glyph.add (g);-		}	+		} 	}  	/** @param character a string with a single glyph or the name of the glyph if it is a ligature. */@@ -153,17 +160,24 @@ public class Text : Widget { 	}  	public double get_sidebearing_extent () {-		double x = 0;-		double ratio = get_scale ();-+		double x ;+		double ratio;+		+		if (likely (sidebearing_extent > 0)) {+			return sidebearing_extent;+		}+		+		x = 0;+		ratio = get_scale ();+		 		iterate ((glyph, kerning, last) => { 			double lsb;-			 			glyph.add_help_lines (); 			lsb = glyph.left_limit; 			x += (glyph.get_width () + kerning) * ratio; 		}); 		+		 		return x; 	} @@ -249,42 +263,76 @@ public class Text : Widget { 		draw_at_baseline (cr, widget_x, y); 	} 	-	public void draw_at_baseline (Context cr, double px, double py) {+	public void draw_at_top (Context cr, double px, double py, int64 cacheid = -1) {+		double s = get_scale ();+		double y = py + s * (font.top_limit - font.base_line);+		draw_at_baseline (cr, px, y, cacheid);+	}+	+	public void set_source_rgba (double r, double g, double b, double a) {+		this.r = r;+		this.g = g;+		this.b = b;+		this.a = a;+	}+	+	public int64 get_cache_id () {+		int64 s = (((int64) font_size) << 32) +			| (((int64) (r * 255)) << 24)+			| (((int64) (g * 255)) << 16)+			| (((int64) (b * 255)) << 8)+			| (((int64) (a * 255)) << 0);+		return s;+	}+	+	public void draw_at_baseline (Context cr, double px, double py, int64 cacheid = -1) { 		double x, y; 		double ratio;-+		Font f;+		double cc_y;+		int64 cache_id = (cacheid < 0) ? get_cache_id () : cacheid;+			 		ratio = get_scale ();-		-		cr.save ();+		f = BirdFont.get_current_font ();+		cc_y = (f.top_limit - f.base_line) * ratio;  		y = py; 		x = px; 					 		iterate ((glyph, kerning, last) => { 			double lsb;+			Surface cache;+			Context cc; 			-			glyph.add_help_lines ();-			-			lsb = glyph.left_limit;-			-			x += kerning * ratio;-			cr.save ();-			cr.new_path ();-			foreach (Path path in glyph.path_list) {-				draw_path (cr, path, lsb, x, y, ratio);+			if (unlikely (!glyph.has_cache (cache_id))) {+				glyph.add_help_lines ();+				+				cache = new Surface.similar (cr.get_target (), Cairo.Content.COLOR_ALPHA, (int) (glyph.get_width () * ratio) + 1, (int) font_size + 1);+				cc = new Context (cache);+				+				lsb = glyph.left_limit;++				cc.save ();+				cc.set_source_rgba (r, g, b, a);+				cc.new_path ();++				foreach (Path path in glyph.path_list) {+					draw_path (cc, path, lsb, 0, cc_y, ratio);+				}+				cc.fill ();+				cc.restore ();++				glyph.set_cache (cache_id, cache); 			}-			cr.fill ();-			cr.restore ();-			++			x += kerning * ratio;+			cr.set_source_surface (glyph.get_cache (cache_id), x, y - cc_y); 			x += glyph.get_width () * ratio;+			+			cr.paint (); 		});-		-		cr.set_source_rgba (0, 0, 0, 1);-		cr.fill ();--		cr.restore ();	-	}	-+	}+	 	void draw_path (Context cr, Path path, double lsb, double x, double y, double scale) { 		EditPoint e, prev; 		double xa, ya, xb, yb, xc, yc, xd, yd;diff --git a/libbirdfont/Renderer/TextArea.vala b/libbirdfont/Renderer/TextArea.valaindex b67e5d9..19e9698 100644--- a/libbirdfont/Renderer/TextArea.vala+++ b/libbirdfont/Renderer/TextArea.vala@@ -49,22 +49,26 @@ public class TextArea : Widget { 	int text_length = 0; 		 	int iter_pos;+	int last_paragraph = 0; 	 	public signal void text_changed (string text); 	Gee.ArrayList<Paragraph> paragraphs = new Gee.ArrayList<Paragraph>  ();+	private static const int DONE = -2;  	-	public TextArea (double font_size = 14) {+	int64 cache_id = -1;+	+	public TextArea (double font_size = 20) { 		this.font_size = font_size; 		width = min_width; 		height = min_height; 	}  	public override double get_height () {-		return height;+		return height + 2 * padding; 	}  	public override double get_width () {-		return width;+		return width + 2 * padding; 	}  	public void set_font_size (double z) {@@ -73,15 +77,24 @@ public class TextArea : Widget { 	 	void generate_paragraphs () { 		Paragraph paragraph;-		string[] p = text.split ("\n");-		double y = 200;++		int next_paragraph = -1;+		+		if (last_paragraph == DONE) {+			return;+		}+	+		next_paragraph = text.index_of ("\n", last_paragraph); 		-		foreach (string t in p) {-			paragraph = new Paragraph (t);+		if (next_paragraph == -1) {+			paragraph = new Paragraph (text.substring (last_paragraph), font_size); 			paragraphs.add (paragraph);-			paragraph.y = y;-			-			y += 200;+			last_paragraph = DONE;+		} else {+			next_paragraph +=  "\n".length;+			paragraph = new Paragraph (text.substring (last_paragraph, next_paragraph - last_paragraph), font_size);+			paragraphs.add (paragraph);+			last_paragraph = next_paragraph; 		} 	} 	@@ -98,6 +111,9 @@ public class TextArea : Widget { 		carret = tl; 		text_length += tl; 		+		paragraphs.clear ();+		generate_paragraphs ();+		 		text_changed (text); 	} 	@@ -224,62 +240,67 @@ public class TextArea : Widget { 		text = nt; 		text_length += tl; 		+		paragraphs.clear (); // DELETE+		generate_paragraphs (); // FIXME:+		 		text_changed (text); 	} 	 	/** @return offset to click in text. */ 	public int layout (double click_x = -1, double click_y = -1) {-		Text word; 		double p; 		double tx, ty; 		string w; 		double xmax = 0; 		double width = this.width - 2 * padding;-		double height = this.height - 2 * padding;-		bool carret_visibility; 		int carret_position = text_length;--		word = new Text ();-		word.set_font_size (font_size); 		 		tx = 0; 		ty = font_size; 		iter_pos = 0;-		while (iter_pos < text_length) {-			w = get_next_word (out carret_visibility, ref iter_pos);-			-			if (w == "") {-				break;-			}--			word.set_text (w);-			-			p = word.get_sidebearing_extent ();-			-			if (!single_line) {-				if (tx + p > width || w == "\n") {-					tx = 0;-					ty += font_size;+										+		foreach (Paragraph paragraph in paragraphs) {+			if (paragraph.need_layout) {+				paragraph.start_y = ty;+				paragraph.start_x = tx;+				+				foreach (Text next_word in paragraph.words) {+					w = next_word.text;+					p = next_word.get_sidebearing_extent (); 					-					if (ty + widget_y > 2 * allocation.height) {-						height = widget_y + 2 * allocation.height;+					if (w == "") { 						break; 					}++					if (!single_line) {+						if (tx + p > width || w == "\n") {+							tx = 0;+							ty += next_word.font_size;+						}+					}+					+					if (widget_y + ty - font_size <= click_y <= widget_y + ty + padding+						&& widget_x + tx <= click_x) {+						carret_position = find_carret_pos_in_word (next_word, iter_pos, tx, click_x);+					}+												+					if (w != "\n") {+						tx += p;+					}+					+					if (tx > xmax) {+						xmax = tx;+					} 				}+				+				paragraph.width = xmax;+				paragraph.end_x = tx;+				paragraph.end_y = ty;+				paragraph.need_layout = false; 			}-			-			if (widget_y + ty - font_size <= click_y <= widget_y + ty + padding-				&& widget_x + tx <= click_x) {-				carret_position = find_carret_pos_in_word (word, iter_pos, tx, click_x);-			}-										-			if (w != "\n") {-				tx += p;-			}-			-			if (tx > xmax) {-				xmax = tx;-			}+									+			tx = paragraph.end_x;+			ty = paragraph.end_y; 		} 		 		this.width = min_width;@@ -293,7 +314,16 @@ public class TextArea : Widget { 		if (click_x > 0 && click_x < widget_x + padding) { 			carret_position = 0; 		}-				++		if (last_paragraph != DONE) {+			this.height = (text_length / (double) last_paragraph) * ty + 2 * padding; // estimate height+		}+		+		if (ty + widget_y < allocation.height && last_paragraph != DONE) {+			generate_paragraphs ();+			return layout (click_x, click_y);+		}+		 		return carret_position; 	} 	@@ -313,6 +343,7 @@ public class TextArea : Widget { 			i += ((!) glyph.get_unichar ().to_string ()).length; 			wx += (glyph.get_width () + kerning) * ratio; 			d = Math.fabs (wx - click_x);+			 			if (d < min_d) { 				min_d = d; 				carret_position = iter_pos - w.length + i;@@ -375,6 +406,7 @@ public class TextArea : Widget { 			// border 			cr.save (); 			cr.set_line_width (1);+			cr.set_source_rgba (0, 0, 0, 1); 			draw_rounded_rectangle (cr, x, y, this.width, this.height, padding); 			cr.stroke (); 			cr.restore ();@@ -395,6 +427,8 @@ public class TextArea : Widget { 		} 		 		// draw selection background+		// FIXME: put back+		/* 		if (selection_end >= 0 && selection_end != carret) { 			tx = 0; 			ty = 0;@@ -451,8 +485,89 @@ public class TextArea : Widget { 			 			cr.restore (); 		}+		*/++		tx = 0;+		ty = 0;	+		+		int first_visible = 0;+		int last_visible;+		int paragraphs_size = paragraphs.size;+		while (first_visible < paragraphs_size) {+			if (paragraphs.get (first_visible).text_is_on_screen (allocation, widget_y)) {+				break;+			}+			first_visible++;+		}+		+		last_visible = first_visible;+		while (last_visible < paragraphs_size) {+			if (!paragraphs.get (last_visible).text_is_on_screen (allocation, widget_y)) {+				last_visible++;+				break;+			}+			last_visible++;+		}	+		+		if (paragraphs_size == 0) {+			return;+		}+		+		Context cc; // cached context+		double cc_x, cc_y;+		Paragraph paragraph;+		paragraph = paragraphs.get (0); 		+		tx = paragraph.start_x;+		ty = paragraph.start_y;++		if (cache_id == -1 && paragraphs.size > 0 && paragraphs.get (0).words.size > 0) {+			Text t = paragraphs.get (0).words.get (0);+			t.set_source_rgba (0, 0, 0, 1);+			cache_id = t.get_cache_id ();+		}+				+		for (int i = first_visible; i < last_visible; i++) { +			paragraph = paragraphs.get (i);+			+			tx = paragraph.start_x;+			ty = paragraph.start_y; +			if (paragraph.cached_surface == null) {		+				paragraph.cached_surface = new Surface.similar (cr.get_target (), Cairo.Content.COLOR_ALPHA, paragraph.get_width (), paragraph.get_height () + (int) font_size + 1);+				cc = new Context ((!) paragraph.cached_surface);+		+				cc_x = paragraph.start_x;+				cc_y = 0;+				+				foreach (Text next_word in paragraph.words) {+					w = next_word.text;+					+					next_word.set_source_rgba (0, 0, 0, 1);+					+					p = next_word.get_sidebearing_extent ();+					+					if (cc_x + p > width || w == "\n") {+						cc_x = 0;+						cc_y += next_word.font_size;+					}+					+					if (w != "\n") {+						next_word.draw_at_top (cc, cc_x, cc_y, cache_id);+						cc_x += p;+					}+				}+			}+			+			if (likely (paragraph.cached_surface != null)) {+				cr.set_source_surface ((!) paragraph.cached_surface, x + tx, widget_y + paragraph.start_y - font_size + padding);+				cr.paint ();+			} else {+				warning ("No paragraph image.");+			}+		}+		+/* 		// draw characters 		tx = 0; 		ty = 0;@@ -486,6 +601,7 @@ public class TextArea : Widget { 			} 		} 		cr.restore ();+		*/ 	} 	 	void draw_carret_at (Context cr, double x, double y) {@@ -569,15 +685,120 @@ public class TextArea : Widget { 	} 	 	class Paragraph : GLib.Object {-		public double x = -1;-		public double y = -1;+		public double end_x = -10000;+		public double end_y = -10000;+		+		public double start_x = -10000;+		public double start_y = -10000;+		+		public double width = -10000;+		 		public string text; 		public Gee.ArrayList<Text> words = new Gee.ArrayList<Text> (); 		-		public Paragraph (string text) {+		int text_length;+		+		public bool need_layout = true;+		+		public Surface? cached_surface = null;+		+		public Paragraph (string text, double font_size) { 			this.text = text;+			text_length = text.length;+			generate_words (font_size);+		}++		public int get_height () {+			return (int) (end_y - start_y) + 1;+		}+		+		public int get_width () {+			return (int) width + 1; 		} 		+		public bool text_is_on_screen (WidgetAllocation alloc, double widget_y) {+			bool v = (0 <= start_y + widget_y <= alloc.height)+				|| (0 <= end_y + widget_y <= alloc.height)+				|| (start_y + widget_y <= 0 && alloc.height <= end_y + widget_y);+			return v;+		}++		void generate_words (double font_size) {+			string w;+			int p = 0;+			bool carret_at_word_end = false;+			Text word;+			int carret = 0;+			int iter_pos = 0;++			while (p < text_length) {+				w = get_next_word (out carret_at_word_end, ref iter_pos, carret);+				+				if (w == "") {+					break;+				}+				+				word = new Text (w, font_size);+				words.add (word);+			}+		}++		string get_next_word (out bool carret_at_end_of_word, ref int iter_pos, int carret) {+			int i;+			int ni;+			int pi;+			string n;+			int nl;+			+			carret_at_end_of_word = false;+			+			if (iter_pos >= text_length) {+				carret_at_end_of_word = true;+				return "".dup ();+			}+			+			if (text.get_char (iter_pos) == '\n') {+				iter_pos += "\n".length;+				carret_at_end_of_word = (iter_pos == carret);+				return "\n".dup ();+			}+			+			i = text.index_of (" ", iter_pos);+			pi = i + " ".length;+			+			ni = text.index_of ("\t", iter_pos);+			if (ni != -1 && ni < pi || i == -1) {+				i = ni;+				pi = i  + "\t".length;+			}+			+			ni = text.index_of ("\n", iter_pos);+			if (ni != -1 && ni < pi || i == -1) {+				i = ni;+				pi = i;+			}+			+			if (iter_pos + iter_pos - pi > text_length || i == -1) {+				n = text.substring (iter_pos);+			} else {+				n = text.substring (iter_pos, pi - iter_pos);+			}+			+			nl = n.length;+			if (iter_pos < carret < iter_pos + nl) {+				n = text.substring (iter_pos, carret - iter_pos);+				nl = n.length;+				carret_at_end_of_word = true;+			}+			+			iter_pos += nl;+			+			if (iter_pos == carret) {+				carret_at_end_of_word = true;+			}+			+			return n;+		} 	} } diff --git a/libbirdfont/SettingsItem.vala b/libbirdfont/SettingsItem.valaindex fcc7a28..de942d0 100644--- a/libbirdfont/SettingsItem.vala+++ b/libbirdfont/SettingsItem.vala@@ -66,7 +66,7 @@ class SettingsItem : GLib.Object { 			cr.restore (); 				 			cr.save ();-			cr.set_source_rgba (1, 1, 1, 1);+			label.set_source_rgba (1, 1, 1, 1); 			label.set_font_size (20 * MainWindow.units); 			label.draw_at_baseline (cr, 21 * MainWindow.units, y + 25 * MainWindow.units); 			cr.restore ();diff --git a/libbirdfont/TabBar.vala b/libbirdfont/TabBar.valaindex c5918c3..0f67984 100644--- a/libbirdfont/TabBar.vala+++ b/libbirdfont/TabBar.vala@@ -780,9 +780,9 @@ public class TabBar : GLib.Object { 			center_y = tab_height / 2.0 + 4 / scale; 			 			if (tab_index == selected) {-				cr.set_source_rgba (40 / 255.0, 57 / 255.0, 65 / 255.0, 1);+				label.set_source_rgba (40 / 255.0, 57 / 255.0, 65 / 255.0, 1); 			} else {-				cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+				label.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1); 			} 			 			label.set_font_size (text_height);diff --git a/libbirdfont/Widget.vala b/libbirdfont/Widget.valaindex c53853a..8c3667a 100644--- a/libbirdfont/Widget.vala+++ b/libbirdfont/Widget.vala@@ -47,6 +47,12 @@ public abstract class Widget : GLib.Object { 		return widget_x <= x <= widget_x + get_width ()  			&&  widget_y <= y <= widget_y + get_height (); 	}+	+	public bool is_on_screen () {+		return (widget_y <= 0 <= widget_y + get_height ())+			|| (widget_y <= allocation.height <= widget_y + get_height ())+			|| (0 <= widget_y <= allocation.height);+	} }  }

Contact

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