The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

GlyphSequence.vala in libbirdfont

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdfont/GlyphSequence.vala.
Thread safety in text rendering
1 /* 2 Copyright (C) 2013 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 namespace BirdFont { 15 16 public class GlyphSequence { 17 18 /** A list of all glyphs */ 19 public Gee.ArrayList<Glyph?> glyph; 20 21 /** A list of corresponding glyph ranges if applicable. */ 22 public Gee.ArrayList<GlyphRange?> ranges; 23 24 public GlyphSequence () { 25 glyph = new Gee.ArrayList<Glyph?> (); 26 ranges = new Gee.ArrayList<GlyphRange?> (); 27 } 28 29 public int length () { 30 return glyph.size; 31 } 32 33 /** Do ligature substitution. 34 * @return a new sequence with ligatures 35 */ 36 public GlyphSequence process_ligatures () { 37 // FIXME add range to ligature 38 GlyphSequence ligature_sequence = new GlyphSequence (); 39 Font font = BirdFont.get_current_font (); 40 bool has_range = false; 41 Ligatures ligatures; 42 43 foreach (Glyph? g in glyph) { 44 ligature_sequence.glyph.add (g); 45 } 46 47 foreach (GlyphRange? r in ranges) { 48 ligature_sequence.ranges.add (r); 49 if (r != null) { 50 has_range = true; 51 } 52 } 53 54 // skip ligature substitution if this sequence contains ranges 55 if (has_range) { 56 return ligature_sequence; 57 } 58 59 ligatures = font.get_ligatures (); 60 ligatures.get_single_substitution_ligatures ((substitute, ligature) => { 61 ligature_sequence.replace (substitute, ligature.get_current ()); 62 }); 63 64 ligature_sequence.ranges.clear (); 65 for (int i = 0; i < ligature_sequence.glyph.size; i++) { 66 ligature_sequence.ranges.add (null); 67 } 68 69 return ligature_sequence; 70 } 71 72 void replace (GlyphSequence old, Glyph replacement) { 73 int i = 0; 74 while (i < glyph.size) { 75 if (starts_with (old, i)) { 76 substitute (i, old.glyph.size, replacement); 77 i = 0; 78 } else { 79 i++; 80 } 81 } 82 } 83 84 bool starts_with (GlyphSequence old, uint index) { 85 Glyph? gl; 86 87 foreach (Glyph? g in old.glyph) { 88 if (index >= glyph.size) { 89 return false; 90 } 91 92 gl = glyph.get ((int) index); 93 94 if (g != gl) { 95 return false; 96 } 97 98 index++; 99 } 100 101 return true; 102 } 103 104 void substitute (uint index, uint length, Glyph substitute) { 105 Gee.ArrayList<Glyph?> new_list = new Gee.ArrayList<Glyph?> (); 106 int i = 0; 107 108 foreach (Glyph? g in glyph) { 109 if (i == index) { 110 new_list.add (substitute); 111 } 112 113 if (!(i >= index && i < index + length)) { 114 new_list.add (g); 115 } 116 117 i++; 118 } 119 120 glyph = new_list; 121 } 122 } 123 124 } 125