The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

SpacingTab.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/SpacingTab.vala.
Merge ../birdfont-2.x
1 /* 2 Copyright (C) 2015 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 15 using Cairo; 16 17 namespace BirdFont { 18 19 /** Kerning context. */ 20 public class SpacingTab : KerningDisplay { 21 22 double box_size = 122 * MainWindow.units; 23 double height = 44 * MainWindow.units; 24 double character_height = 20 * MainWindow.units; 25 26 WidgetAllocation allocation; 27 28 Glyph text_input_glyph; 29 30 public SpacingTab () { 31 allocation = new WidgetAllocation (); 32 adjust_side_bearings = true; 33 } 34 35 public override string get_label () { 36 return t_("Spacing"); 37 } 38 39 public override string get_name () { 40 return "Spacing"; 41 } 42 43 public override void draw (WidgetAllocation allocation, Context cr) { 44 base.draw (allocation, cr); 45 draw_spacing_metrix (allocation, cr); 46 } 47 48 void draw_spacing_metrix (WidgetAllocation allocation, Context cr) { 49 GlyphSequence row; 50 int index; 51 Font font = BirdFont.get_current_font (); 52 53 // background 54 cr.save (); 55 Theme.color (cr, "Background 1"); 56 cr.rectangle (0, allocation.height - height, allocation.width, height); 57 cr.fill (); 58 cr.restore (); 59 60 // character bar 61 cr.save (); 62 Theme.color (cr, "Table Border"); 63 cr.set_line_width (0.8); 64 cr.move_to (0, allocation.height - height); 65 cr.line_to (allocation.width, allocation.height - height); 66 cr.stroke (); 67 68 cr.move_to (0, allocation.height - height + character_height); 69 cr.line_to (allocation.width, allocation.height - height + character_height); 70 cr.stroke (); 71 cr.restore (); 72 73 row = get_first_row ().process_ligatures (font); 74 index = 0; 75 foreach (Glyph? g in row.glyph) { 76 draw_glyph_spacing (allocation, cr, g, index); 77 index++; 78 } 79 } 80 81 void draw_glyph_spacing (WidgetAllocation allocation, Context cr, Glyph? glyph, int index) { 82 Glyph g; 83 double end, middle; 84 double l, r; 85 Text left, right, cap; 86 unichar c; 87 88 this.allocation = allocation; 89 90 // end mark 91 end = (index + 1) * box_size; 92 cr.save (); 93 cr.set_source_rgba (0.5, 0.5, 0.5, 1); 94 cr.set_line_width (2); 95 cr.move_to (end, allocation.height - height); 96 cr.line_to (end, allocation.height); 97 cr.stroke (); 98 cr.restore (); 99 100 // boxes 101 middle = end - box_size / 2.0; 102 cr.save (); 103 cr.set_source_rgba (0.5, 0.5, 0.5, 1); 104 cr.set_line_width (0.8); 105 cr.move_to (middle, allocation.height - height + character_height); 106 cr.line_to (middle, allocation.height); 107 cr.stroke (); 108 cr.restore (); 109 110 if (glyph != null) { 111 g = (!) glyph; 112 113 c = g.get_unichar (); 114 cap = new Text ((!) c.to_string (), 17); 115 Theme.text_color (cap, "Table Border"); 116 cap.widget_x = middle - cap.get_extent () / 2.0; 117 cap.widget_y = allocation.height - height + character_height - 4 * MainWindow.units; 118 cap.draw_at_baseline (cr, cap.widget_x, cap.widget_y); 119 120 l = g.get_left_side_bearing (); 121 122 if (Math.fabs (l) < 0.001) { 123 l = 0; 124 } 125 126 left = new Text (truncate (l, 5), 17); 127 Theme.text_color (left, "Foreground 1"); 128 left.widget_x = middle - box_size / 2.0 + (box_size / 2.0 - left.get_extent ()) / 2.0; 129 left.widget_y = allocation.height - 7 * MainWindow.units; 130 left.draw_at_baseline (cr, left.widget_x, left.widget_y); 131 132 r = g.get_right_side_bearing (); 133 134 if (Math.fabs (r) < 0.001) { 135 r = 0; 136 } 137 138 right = new Text (truncate (r, 5), 17); 139 Theme.text_color (right, "Table Border"); 140 right.widget_x = end - (box_size / 2.0 - right.get_extent ()) / 2.0 - right.get_extent (); 141 right.widget_y = allocation.height - 7 * MainWindow.units; 142 right.draw_at_baseline (cr, right.widget_x, right.widget_y); 143 } 144 } 145 146 public string truncate (double f, int digits) { 147 string t = @"$f"; 148 string s = ""; 149 150 int d = digits; 151 int i; 152 unichar c; 153 154 if (t.index_of ("-") != -1) { 155 d++; 156 } 157 158 if (t.index_of (".") != -1) { 159 d++; 160 } 161 162 i = 0; 163 while (t.get_next_char (ref i, out c)) { 164 s = s + (!) c.to_string (); 165 166 if (i >= d) { 167 break; 168 } 169 } 170 171 return s; 172 } 173 174 public override void button_press (uint button, double ex, double ey) { 175 if (button == 3) { 176 return; 177 } 178 179 if (!(ey >= allocation.height - height)) { 180 base.button_press (button, ex, ey); 181 } 182 } 183 184 public override void button_release (int button, double ex, double ey) { 185 GlyphSequence row; 186 double p; 187 Font font = BirdFont.get_current_font (); 188 189 if (button == 3) { 190 return; 191 } 192 193 if (ey >= allocation.height - height) { 194 195 TabContent.hide_text_input (); 196 197 // TODO: add button for processing ligatures 198 row = get_first_row ().process_ligatures (font); 199 p = 0; 200 foreach (Glyph? g in row.glyph) { 201 if (p < ex < p + box_size / 2.0) { 202 update_lsb (g); 203 } 204 205 if (p + box_size / 2.0 < ex < p + box_size) { 206 update_rsb (g); 207 } 208 209 p += box_size; 210 } 211 } else { 212 base.button_release (button, ex, ey); 213 } 214 } 215 216 void update_lsb (Glyph? g) { 217 TextListener listener; 218 string submitted_value = ""; 219 double l; 220 221 if (g == null) { 222 return; 223 } 224 225 text_input_glyph = (!) g; 226 l = text_input_glyph.get_left_side_bearing (); 227 228 if (Math.fabs (l) < 0.001) { 229 l = 0; 230 } 231 232 listener = new TextListener (t_("Left"), @"$(l)", t_("Set")); 233 234 listener.signal_text_input.connect ((text) => { 235 submitted_value = text; 236 237 if (MenuTab.has_suppress_event ()) { 238 return; 239 } 240 241 GlyphCanvas.redraw (); 242 }); 243 244 listener.signal_submit.connect (() => { 245 double v; 246 TabContent.hide_text_input (); 247 248 text_input = false; 249 suppress_input = false; 250 251 v = double.parse (submitted_value); 252 text_input_glyph.left_limit -= v - text_input_glyph.get_left_side_bearing (); 253 }); 254 255 suppress_input = true; 256 text_input = true; 257 TabContent.show_text_input (listener); 258 } 259 260 void update_rsb (Glyph? g) { 261 TextListener listener; 262 string submitted_value = ""; 263 double r; 264 265 if (g == null) { 266 return; 267 } 268 269 text_input_glyph = (!) g; 270 r = text_input_glyph.get_right_side_bearing (); 271 272 if (Math.fabs (r) < 0.001) { 273 r = 0; 274 } 275 276 listener = new TextListener (t_("Right"), @"$(r)", t_("Set")); 277 278 listener.signal_text_input.connect ((text) => { 279 submitted_value = text; 280 281 if (MenuTab.has_suppress_event ()) { 282 return; 283 } 284 285 GlyphCanvas.redraw (); 286 }); 287 288 listener.signal_submit.connect (() => { 289 double v; 290 TabContent.hide_text_input (); 291 292 text_input = false; 293 suppress_input = false; 294 295 v = double.parse (submitted_value); 296 text_input_glyph.right_limit += v - text_input_glyph.get_right_side_bearing (); 297 }); 298 299 suppress_input = true; 300 text_input = true; 301 TabContent.show_text_input (listener); 302 } 303 304 public override bool needs_modifier () { 305 return true; 306 } 307 308 } 309 310 } 311