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 : GLib.Object { 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 (Font font) { 37 // FIXME add range to ligature 38 GlyphSequence ligature_sequence = new GlyphSequence (); 39 bool has_range = false; 40 Ligatures ligatures; 41 42 foreach (Glyph? g in glyph) { 43 ligature_sequence.glyph.add (g); 44 } 45 46 foreach (GlyphRange? r in ranges) { 47 ligature_sequence.ranges.add (r); 48 if (r != null) { 49 has_range = true; 50 } 51 } 52 53 // skip ligature substitution if this sequence contains ranges 54 if (has_range) { 55 return ligature_sequence; 56 } 57 58 ligatures = font.get_ligatures (); 59 ligatures.get_single_substitution_ligatures ((substitute, ligature) => { 60 ligature_sequence.replace (substitute, ligature.get_current ()); 61 }); 62 63 ligature_sequence.ranges.clear (); 64 for (int i = 0; i < ligature_sequence.glyph.size; i++) { 65 ligature_sequence.ranges.add (null); 66 } 67 68 return ligature_sequence; 69 } 70 71 void replace (GlyphSequence old, Glyph replacement) { 72 int i = 0; 73 while (i < glyph.size) { 74 if (starts_with (old, i)) { 75 substitute (i, old.glyph.size, replacement); 76 i = 0; 77 } else { 78 i++; 79 } 80 } 81 } 82 83 bool starts_with (GlyphSequence old, uint index) { 84 Glyph? gl; 85 86 foreach (Glyph? g in old.glyph) { 87 if (index >= glyph.size) { 88 return false; 89 } 90 91 gl = glyph.get ((int) index); 92 93 if (g != gl) { 94 return false; 95 } 96 97 index++; 98 } 99 100 return true; 101 } 102 103 void substitute (uint index, uint length, Glyph substitute) { 104 Gee.ArrayList<Glyph?> new_list = new Gee.ArrayList<Glyph?> (); 105 int i = 0; 106 107 foreach (Glyph? g in glyph) { 108 if (i == index) { 109 new_list.add (substitute); 110 } 111 112 if (!(i >= index && i < index + length)) { 113 new_list.add (g); 114 } 115 116 i++; 117 } 118 119 glyph = new_list; 120 } 121 } 122 123 } 124