.
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