Clone in a terminal:
Commit 8b1a73e
Johan Mattsson - 2014-11-25T14:36:58+00:00
8b1a73e9ed20cfec2eafe3d535e0259786756a54johan.mattsson.m@gmail.com

Fix carret position in text area

Changed files (5)

Diff

diff --git a/libbirdfont/GlyphSequence.vala b/libbirdfont/GlyphSequence.valaindex 0a6ab7b..c442e9a 100644--- a/libbirdfont/GlyphSequence.vala+++ b/libbirdfont/GlyphSequence.vala@@ -26,6 +26,10 @@ public class GlyphSequence { 		ranges = new Gee.ArrayList<GlyphRange?> (); 	} 	+	public int length () {+		return glyph.size;+	}+	 	/** Do ligature substitution. 	 * @return a new sequence with ligatures 	 */diff --git a/libbirdfont/KerningClasses.vala b/libbirdfont/KerningClasses.valaindex b52fe4e..7b78174 100644--- a/libbirdfont/KerningClasses.vala+++ b/libbirdfont/KerningClasses.vala@@ -54,8 +54,9 @@ public class KerningClasses : GLib.Object {  	/** Class based gpos kerning. */ 	public double get_kerning_for_pair (string a, string b, GlyphRange? gr_left, GlyphRange? gr_right) {-		double k;+		double k = 0; 		GlyphRange grl, grr;+		 		try { 			if (gr_left == null) { 				grl = new GlyphRange ();@@ -70,11 +71,16 @@ public class KerningClasses : GLib.Object { 			} else { 				grr = (!) gr_right; 			}-			++			if (gr_left == null && gr_right == null) {+				k = get_kerning (a, b);+				return k;+			}+						 			if (gr_left != null && gr_right != null) { 				return get_kerning_for_range (grl, grr); 			}-+			 			if (gr_left != null && gr_right == null) { 				return get_kern_for_range_to_char (grl, b); 			}@@ -82,16 +88,13 @@ public class KerningClasses : GLib.Object { 			if (gr_left == null && gr_right != null) { 				return get_kern_for_char_to_range (a, grr); 			}-			-			if (gr_left == null && gr_right == null) {-				k = get_kerning (a, b);-				return k;-			}			 		} catch (MarkupError e) { 			warning (e.message); 		} 		-		warning ("no kerning found");+		if (unlikely (k == 0)) {+			warning ("no kerning found");+		} 		 		return 0; 	}diff --git a/libbirdfont/Renderer/Text.vala b/libbirdfont/Renderer/Text.valaindex 3f3da2d..d5a0edd 100644--- a/libbirdfont/Renderer/Text.vala+++ b/libbirdfont/Renderer/Text.vala@@ -40,7 +40,19 @@ public class Text : Widget { 	FontCache font_cache; 	Font? current_font; 	public string text;-	GlyphSequence glyph_sequence;+	+	GlyphSequence glyph_sequence {+		get {+			if (gs == null) {+				gs = generate_glyphs ();+			}+			+			return (!) gs;+		}+	}+	+	GlyphSequence? gs = null;+	 	public delegate void Iterator (Glyph glyph, double kerning, bool last); 	public double font_size; 	public double sidebearing_extent = 0;@@ -53,11 +65,10 @@ public class Text : Widget { 	public Text (string text = "", double size = 17, double margin_bottom = 0) { 		current_font = null; 		this.margin_bottom = margin_bottom;-		glyph_sequence = new GlyphSequence (); 		font_cache = FontCache.get_default_cache (); 		-		set_text (text); 		set_font_size (size);+		set_text (text); 	}  	public void set_font_size (double height_in_pixels) {@@ -70,20 +81,27 @@ public class Text : Widget { 	} 	 	public void set_text (string text) {	+		this.text = text;+		gs = null;+	}++	private GlyphSequence generate_glyphs () { 		int index; 		unichar c; 		string name; 		Glyph? g;+		GlyphSequence gs; 		-		this.text = text;-		glyph_sequence = new GlyphSequence ();+		gs = new GlyphSequence (); 		 		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);-			glyph_sequence.glyph.add (g);+			gs.glyph.add (g); 		}+		+		return gs; 	}  	/** @param character a string with a single glyph or the name of the glyph if it is a ligature. */@@ -100,6 +118,7 @@ public class Text : Widget { 		GlyphRange? gr_left, gr_right; 		GlyphSequence word; 		Glyph? g;+		KerningClasses kc; 		 		glyph = new Glyph ("", '\0'); @@ -109,10 +128,14 @@ public class Text : Widget { 		 		word = glyph_sequence; 		wi = 0;+ 		word_with_ligatures = word.process_ligatures ();+		 		gr_left = null; 		gr_right = null;+		kc = font.get_kerning_classes (); 		for (int i = 0; i < word_with_ligatures.glyph.size; i++) {+ 			g = word_with_ligatures.glyph.get (i); 			 			if (g == null || prev == null || wi == 0) {@@ -124,7 +147,7 @@ public class Text : Widget { 				gr_left = word_with_ligatures.ranges.get (wi - 1); 				gr_right = word_with_ligatures.ranges.get (wi); -				kern = font.get_kerning_classes ().get_kerning_for_pair (((!)prev).get_name (), ((!)g).get_name (), gr_left, gr_right);+				kern = kc.get_kerning_for_pair (((!) prev).get_name (), ((!) g).get_name (), gr_left, gr_right); 			} 					 			// process glyph@@ -169,10 +192,13 @@ public class Text : Widget { 		 		x = 0; 		ratio = get_scale ();-		++		if (unlikely (ratio == 0)) {+			warning ("No scale.");+		}+				 		iterate ((glyph, kerning, last) => { 			double lsb;-			glyph.add_help_lines (); 			lsb = glyph.left_limit; 			x += (glyph.get_width () + kerning) * ratio; 		});diff --git a/libbirdfont/Renderer/TextArea.vala b/libbirdfont/Renderer/TextArea.valaindex 59955ea..8121732 100644--- a/libbirdfont/Renderer/TextArea.vala+++ b/libbirdfont/Renderer/TextArea.vala@@ -108,6 +108,8 @@ public class TextArea : Widget { 		unichar c; 		TextUndoItem ui; 		+		Test t = new Test.time ("key_press");+		 		c = (unichar) keyval; 		 		switch (c) {@@ -204,6 +206,8 @@ public class TextArea : Widget { 				break; 		} 		+		if (t.get_time () > 0.1) t.print ();+		 		GlyphCanvas.redraw (); 	} 	@@ -213,7 +217,10 @@ public class TextArea : Widget { 		TextArea focus; 		TextUndoItem ui; 		-		if (!is_modifier_key (keyval)) {+		if (!is_modifier_key (keyval) +			&& !KeyBindings.has_ctrl ()+			&& !KeyBindings.has_alt ()) {+			 			s = (!) c.to_string ();		 			 			if (s.validate ()) {				@@ -356,9 +363,11 @@ public class TextArea : Widget { 		same = selection_start.paragraph == selection_stop.paragraph; 		 		if (!same) {+			return_val_if_fail (0 <= selection_start.paragraph < paragraphs.size, ui); 			pg = paragraphs.get (selection_start.paragraph); 			s = pg.text.substring (0, selection_start.character_index); +			return_val_if_fail (0 <= selection_stop.paragraph < paragraphs.size, ui); 			pge = paragraphs.get (selection_stop.paragraph); 			e = pge.text.substring (selection_stop.character_index); 							@@ -376,6 +385,8 @@ public class TextArea : Widget { 				pge.set_text (e); 			} 		} else {+			return_val_if_fail (0 <= selection_start.paragraph < paragraphs.size, ui);+			 			pg = paragraphs.get (selection_start.paragraph); 			n = pg.text.substring (0, selection_start.character_index); 			n += pg.text.substring (selection_stop.character_index);@@ -395,12 +406,13 @@ public class TextArea : Widget { 		} 		 		for (i = selection_stop.paragraph - 1; i > selection_start.paragraph; i--) {-			return_if_fail (0 <= i < paragraphs.size);+			return_val_if_fail (0 <= i < paragraphs.size, ui); 			ui.deleted.add (paragraphs.get (i)); 			paragraphs.remove_at (i); 		} 		 		if (s == "" && !same) {+			return_val_if_fail (0 <= selection_start.paragraph < paragraphs.size, ui); 			paragraphs.remove_at (selection_start.paragraph); 		} 		@@ -609,7 +621,7 @@ public class TextArea : Widget { 				pgs.add (s); 			} 		}-+		 		if (has_selection () && show_selection) { 			ui = delete_selected_text (); 			u = true;@@ -648,7 +660,7 @@ public class TextArea : Widget {  			carret.paragraph = paragraph_index; 			carret.character_index = next_paragraph.text.length;-			+ 			next_paragraph.set_text (next_paragraph.text + end); 		} 		@@ -659,16 +671,22 @@ public class TextArea : Widget {  		update_paragraph_index (); 		layout ();+				 		text_changed (get_text ()); 		show_selection = false; 	} 	+	// FIXME: corruption? 	public string get_text () {+		Test b = new Test.time ("get txt"); 		StringBuilder sb = new StringBuilder ();+		 		foreach (Paragraph p in paragraphs) { 			sb.append (p.text); 		}-		return sb.str;+		if (b.get_time () > 0.1) b.print ();+		+		return sb.str.dup (); 	} 	 	Carret get_carret_at (double click_x, double click_y, bool check_boundaries = true) {@@ -772,7 +790,6 @@ public class TextArea : Widget { 		double tx, ty; 		string w; 		double xmax = 0;-		double width = this.width - 2 * padding; 		int i = 0; 		double dd; 		bool on_screen;@@ -781,25 +798,34 @@ public class TextArea : Widget { 		ty = font_size;  		for (i = paragraphs.size - 1; i >= 0 && paragraphs.size > 1; i--) {-			if (paragraphs.get (i).is_empty ()) {+			if (unlikely (paragraphs.get (i).is_empty ())) {+				warning ("Empty paragraph."); 				paragraphs.remove_at (i);+				update_paragraph_index (); 			} 		}-+		 		i = 0;-		foreach (Paragraph paragraph in paragraphs) {			+		foreach (Paragraph paragraph in paragraphs) { 			if (paragraph.need_layout  				|| (paragraph.text_area_width != width 					&& paragraph.text_is_on_screen (allocation, widget_y))) {-+						 				paragraph.start_y = ty; 				paragraph.start_x = tx;-				paragraph.text_area_width = width;+				+				paragraph.cached_surface = null; 				 				foreach (Text next_word in paragraph.words) {+					next_word.set_font_size (font_size);+					 					w = next_word.text; 					p = next_word.get_sidebearing_extent ();-					++					if (unlikely (p == 0)) {+						warning (@"Zero width word: $(w)");+					}+ 					if (w == "") { 						break; 					}@@ -812,7 +838,7 @@ public class TextArea : Widget { 						ty += next_word.font_size; 					} else { 						if (!single_line) {-							if (tx + p > width || w == "\n") {+							if (tx + p + 2 * padding > width || w == "\n") { 								tx = 0; 								ty += next_word.font_size; 							}@@ -830,17 +856,22 @@ public class TextArea : Widget { 						} 					} 				}-				+ 				if (tx > xmax) { 					xmax = tx; 				}-					+				+				paragraph.text_area_width = width; 				paragraph.width = xmax; 				paragraph.end_x = tx; 				paragraph.end_y = ty; 				paragraph.need_layout = false; 			}-									+				+			if (xmax > width) {+				break;+			}+								 			tx = paragraph.end_x; 			ty = paragraph.end_y; 			i++;@@ -917,7 +948,11 @@ public class TextArea : Widget { 		double carret_x; 		double carret_y; 		+		Test t0 = new Test.time ("layout");+		 		layout ();+		+		if (t0.get_time () > 0.1) t0.print ();  		if (draw_border) { 			// background@@ -943,7 +978,6 @@ public class TextArea : Widget { 		 		width = this.width - padding; 		x += padding;-		word.set_font_size (font_size); 		scale = word.get_scale (); 		y += font_size; 		@@ -1062,6 +1096,8 @@ public class TextArea : Widget { 		tx = paragraph.start_x; 		ty = paragraph.start_y; +		Test t1 = new Test.time ("draw");+ 		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);@@ -1095,6 +1131,8 @@ public class TextArea : Widget { 			} 		} +		if (t1.get_time () > 0.1) t1.print ();+ 		if (carret_is_visible) { 			get_carret_position (carret, out carret_x, out carret_y); 			@@ -1145,14 +1183,19 @@ public class TextArea : Widget { 				pos_y = widget_y + next_word.widget_y + next_word.get_baseline_to_bottom ();		 			} else if (carret.character_index >= ch_index + wl) { 				pos_x = next_word.widget_x + next_word.get_sidebearing_extent () + widget_x + padding;-				pos_y = widget_y + next_word.widget_y + next_word.get_baseline_to_bottom ();		+				pos_y = widget_y + next_word.widget_y + next_word.get_baseline_to_bottom ();+				+				if (next_word.text.has_suffix ("\n")) {+					pos_x = widget_x + padding;+					pos_y += next_word.font_size;+				} 			} else if (ch_index < carret.character_index <= ch_index + wl) { 				tx = widget_x + next_word.widget_x; 				ty = widget_y + next_word.widget_y + next_word.get_baseline_to_bottom (); 		 				if (carret.character_index <= ch_index) {-					pos_x = widget_x;-					pos_y = ty;		+					pos_x = widget_x + padding;+					pos_y = ty; 				}  				next_word.iterate ((glyph, kerning, last) => {@@ -1165,6 +1208,11 @@ public class TextArea : Widget { 					if (ch_index < carret.character_index <= ch_index + ci) { 						pos_x = tx + cw + padding; 						pos_y = ty;+						+						if (glyph.get_unichar () == '\n') {+							pos_x = widget_x + padding;+							pos_y += next_word.font_size;+						} 					} 					 					tx += cw;@@ -1409,6 +1457,8 @@ public class TextArea : Widget { 			int carret = 0; 			int iter_pos = 0; +			return_if_fail (words_in_paragraph.size == 0);+ 			while (p < text_length) { 				w = get_next_word (out carret_at_word_end, ref iter_pos, carret); 				diff --git a/libbirdfont/Test.vala b/libbirdfont/Test.valaindex 657e312..6fe2956 100644--- a/libbirdfont/Test.vala+++ b/libbirdfont/Test.vala@@ -44,7 +44,8 @@ public class Test : Object { 	} 	 	public double get_time () {-		return time_stamp / 1000000.0;+		double stop_time = GLib.get_real_time ();+		return (stop_time - time_stamp) / 1000000.0; 	} 	 	public bool is_benchmark () {

Contact

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