.
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