Commit 0ffc4bc
Thread safety in text rendering
Changed files (10)
modifieddodo.pymodifiedlibbirdfont/Font.valamodifiedlibbirdfont/GlyphRange.valamodifiedlibbirdfont/GlyphSequence.valamodifiedlibbirdfont/KerningClasses.valamodifiedlibbirdfont/KerningDisplay.valamodifiedlibbirdfont/Ligatures.valamodifiedlibbirdfont/Renderer/Text.valamodifiedlibbirdfont/SpacingData.valamodifiedlibbirdfont/SpacingTab.vala
Diff
@@ -88,6 +88,7 @@ def task_pkg_flags(): valac_options = [+ '--thread', '--enable-experimental-non-null', '--enable-experimental', '--target-glib=2.34', # see bug 0000004@@ -132,7 +132,7 @@ public class Font : GLib.Object { bfp_file = new BirdFontPart (this); deleted_glyphs = new Gee.ArrayList<Glyph> ();- ligatures_substitution = new Ligatures ();+ ligatures_substitution = new Ligatures (this); background_images = new Gee.ArrayList<BackgroundImage> (); }@@ -399,7 +399,7 @@ public class GlyphRange { string chr; UniRange r; StringBuilder sb;- unichar c;+ unichar c; if (index > len + unassigned.size) { return "\0".dup();@@ -428,8 +428,14 @@ public class GlyphRange { sb = new StringBuilder (); c = r.get_char ((unichar) (ti + r.length ()));+ + if (unlikely (!c.validate ())) {+ warning ("Not a valid unicode character.");+ return "";+ }+ sb.append_unichar (c);-+ return sb.str; } @@ -13,7 +13,7 @@ */ namespace BirdFont { -public class GlyphSequence {+public class GlyphSequence : GLib.Object { /** A list of all glyphs */ public Gee.ArrayList<Glyph?> glyph;@@ -33,10 +33,9 @@ public class GlyphSequence { /** Do ligature substitution. * @return a new sequence with ligatures */- public GlyphSequence process_ligatures () {+ public GlyphSequence process_ligatures (Font font) { // FIXME add range to ligature GlyphSequence ligature_sequence = new GlyphSequence ();- Font font = BirdFont.get_current_font (); bool has_range = false; Ligatures ligatures; @@ -37,7 +37,7 @@ public class KerningClasses : GLib.Object { /** Ensure that map iterator is not invalidated because of inserts. */ bool protect_map = false; - Font font;+ public Font font; public KerningClasses (Font font) { this.font = font;@@ -122,7 +122,7 @@ public class KerningDisplay : FontDisplay { foreach (GlyphSequence word in row) { wi = 0;- word_with_ligatures = word.process_ligatures ();+ word_with_ligatures = word.process_ligatures (font); gr_left = null; gr_right = null; foreach (Glyph? g in word_with_ligatures.glyph) {@@ -311,7 +311,7 @@ public class KerningDisplay : FontDisplay { } foreach (GlyphSequence word in row) {- word_with_ligatures = word.process_ligatures ();+ word_with_ligatures = word.process_ligatures (font); ranges_index = 0; foreach (Glyph? g in word_with_ligatures.glyph) { @@ -503,8 +503,9 @@ public class KerningDisplay : FontDisplay { Glyph? g; selected_handle = handle; GlyphSequence sequence_with_ligatures;+ Font font = BirdFont.get_current_font (); - sequence_with_ligatures = row.get (0).process_ligatures ();+ sequence_with_ligatures = row.get (0).process_ligatures (font); if (selected_handle <= 0) { selected_handle = 1;@@ -724,6 +725,7 @@ public class KerningDisplay : FontDisplay { int col_index = 0; double fs = KerningTools.font_size; Glyph glyph = new Glyph.no_lines ("");+ Font font = BirdFont.get_current_font (); GlyphRange? gr_left, gr_right; @@ -734,7 +736,7 @@ public class KerningDisplay : FontDisplay { foreach (GlyphSequence word in row) { col_index = 0; - word_with_ligatures = word.process_ligatures ();+ word_with_ligatures = word.process_ligatures (font); foreach (Glyph? g in word_with_ligatures.glyph) { if (g == null) { w = 50;@@ -27,7 +27,10 @@ public class Ligatures : GLib.Object { public delegate void ContextualLigatureIterator (ContextualLigature lig); - public Ligatures () {+ Font font;++ public Ligatures (Font font) {+ this.font = font; } public void get_ligatures (LigatureIterator iter) {@@ -44,7 +47,6 @@ public class Ligatures : GLib.Object { public void get_single_substitution_ligatures (SingleLigatureIterator iter) { get_ligatures ((substitution, ligature) => {- Font font = BirdFont.get_current_font (); GlyphCollection? gc; GlyphCollection li; GlyphSequence gs;@@ -130,6 +130,12 @@ public class Text : Widget { GlyphSequence word; Glyph? g; KerningClasses kc;++ // FIXME: Create a thread safe implementation of the bf text rendering+ // The problem is (probably) in the spacing and kerning code.+ if (MenuTab.suppress_event) {+ return;+ } glyph = new Glyph ("", '\0'); @@ -140,11 +146,12 @@ public class Text : Widget { word = glyph_sequence; wi = 0; - word_with_ligatures = word.process_ligatures ();+ return_if_fail (current_font != null);+ word_with_ligatures = word.process_ligatures ((!) current_font); gr_left = null; gr_right = null;- kc = font.get_kerning_classes ();+ kc = ((!) current_font).get_kerning_classes (); for (int i = 0; i < word_with_ligatures.glyph.size; i++) { g = word_with_ligatures.glyph.get (i);@@ -324,7 +331,9 @@ public class Text : Widget { double x, y; double ratio; double cc_y;- int64 cache_id = (cacheid < 0) ? get_cache_id () : cacheid;+ int64 cache_id;+ + cache_id = (cacheid < 0) ? get_cache_id () : cacheid; ratio = get_scale (); cc_y = (font.top_limit - font.base_line) * ratio;@@ -21,7 +21,7 @@ public class SpacingData : GLib.Object { public KerningClasses kerning_classes; public Gee.ArrayList<SpacingClass> classes = new Gee.ArrayList<SpacingClass> ();- Gee.ArrayList<string> connections = new Gee.ArrayList<string> ();+ Gee.ArrayList<String> connections = new Gee.ArrayList<String> (); public SpacingData (KerningClasses kerning) { kerning_classes = kerning;@@ -32,13 +32,15 @@ public class SpacingData : GLib.Object { } public Gee.ArrayList<string> get_all_connections (string glyph) {+ String s; Gee.ArrayList<string> c = new Gee.ArrayList<string> (); connections.clear ();+ add_connections (glyph); - foreach (string t in connections) {- c.add (t);+ foreach (String t in connections) {+ c.add (t.data.dup ()); } connections.clear ();@@ -46,18 +48,30 @@ public class SpacingData : GLib.Object { return c; } + bool has_connection (string s) {+ foreach (String t in connections) {+ if (t.data == s) {+ return true;+ }+ }+ + return false;+ }+ public void add_connections (string glyph) {- connections.add (glyph);+ String sb = new String (glyph);+ + connections.add (sb); foreach (SpacingClass s in classes) { if (s.first == glyph) {- if (connections.index_of (s.next) == -1) {+ if (has_connection (s.next)) { add_connections (s.next); } } if (s.next == glyph) {- if (connections.index_of (s.first) == -1) {+ if (has_connection (s.first)) { add_connections (s.first); } }@@ -81,7 +95,7 @@ public class SpacingData : GLib.Object { } public void update_kerning (SpacingClass s) {- Font font = BirdFont.get_current_font ();+ Font font = kerning_classes.font; GlyphCollection? g; GlyphCollection gc; @@ -105,6 +119,15 @@ public class SpacingData : GLib.Object { KerningTools.update_spacing_classes (); }+ + class String : GLib.Object {+ + public string data;+ + public String (string s) {+ data = s.dup ();+ } + } } }@@ -47,6 +47,7 @@ public class SpacingTab : KerningDisplay { void draw_spacing_metrix (WidgetAllocation allocation, Context cr) { GlyphSequence row; int index;+ Font font = BirdFont.get_current_font (); // background cr.save ();@@ -69,7 +70,7 @@ public class SpacingTab : KerningDisplay { cr.restore (); // TODO: add button for processing ligatures- row = get_first_row ().process_ligatures ();+ row = get_first_row ().process_ligatures (font); index = 0; foreach (Glyph? g in row.glyph) { draw_glyph_spacing (allocation, cr, g, index);@@ -163,10 +164,11 @@ public class SpacingTab : KerningDisplay { public override void button_press (uint button, double ex, double ey) { GlyphSequence row; double p;+ Font font = BirdFont.get_current_font (); if (ey >= allocation.height - height) { // TODO: add button for processing ligatures- row = get_first_row ().process_ligatures ();+ row = get_first_row ().process_ligatures (font); p = 0; foreach (Glyph? g in row.glyph) { if (p < ex < p + box_size / 2.0) {