The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

ColorPicker.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/ColorPicker.vala.
Parse more style attributes in SVG files
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 public class ColorPicker : Tool { 20 21 double hue = 0; 22 double s = 0; 23 double b = 0; 24 double a = 1; 25 26 public signal void fill_color_updated (); 27 public signal void stroke_color_updated (); 28 public signal void gradient_color_updated (); 29 30 bool update_color = false; 31 public double bar_height; 32 33 int selected_bar = 0; 34 35 public bool has_stroke_color = false; 36 bool stroke_selected = false; 37 38 public Color stroke_color = new Color (0, 0, 0, 1); 39 public Color fill_color = new Color (0, 0, 0, 1); 40 41 public Gradient gradient = new Gradient (); 42 bool update_gradient = false; 43 int bars; 44 Stop current_stop = new Stop (); 45 46 public ColorPicker (string tooltip = "") { 47 base (null, tooltip); 48 49 bar_height = 22 * Toolbox.get_scale (); 50 bars = 5; 51 h = bars * bar_height; 52 53 stroke_color_updated.connect (() => { 54 redraw (); 55 GlyphCanvas.redraw (); 56 }); 57 58 panel_press_action.connect ((selected, button, tx, ty) => { 59 if (y <= ty <= y + bars * bar_height) { 60 update_color = true; 61 selected_bar = (int) ((ty - y) / bar_height); 62 set_color_from_pointer (tx); 63 } 64 }); 65 66 panel_move_action.connect ((selected, button, tx, ty) => { 67 if (update_color) { 68 set_color_from_pointer (tx); 69 } 70 71 return false; 72 }); 73 74 panel_release_action.connect ((selected, button, tx, ty) => { 75 update_color = false; 76 }); 77 } 78 79 public void set_gradient (Gradient g, Stop stop, bool update_gradient) { 80 gradient = g; 81 this.update_gradient = update_gradient; 82 current_stop = stop; 83 redraw (); 84 } 85 86 public void set_color (Color c) { 87 c.to_hsva (out hue, out s, out b, out a); 88 } 89 90 public void set_color_from_pointer (double tx) { 91 if (tx > Toolbox.allocation_width) { 92 tx = Toolbox.allocation_width; 93 } 94 95 if (tx < 0) { 96 tx = 0; 97 } 98 99 if (selected_bar == 0) { 100 hue = (double) tx / Toolbox.allocation_width; 101 } else if (selected_bar == 1) { 102 s = (double) tx / Toolbox.allocation_width; 103 } else if (selected_bar == 2) { 104 b = (double) tx / Toolbox.allocation_width; 105 } else if (selected_bar == 3) { 106 a = (double) tx / Toolbox.allocation_width; 107 } else if (!update_gradient && selected_bar == 4) { 108 if (has_stroke_color) { 109 stroke_selected = tx > Toolbox.allocation_width / 2.0; 110 111 if (stroke_selected) { 112 set_color (stroke_color); 113 } else { 114 set_color (fill_color); 115 } 116 } 117 } else if (update_gradient && selected_bar == 4) { 118 if (gradient.stops.size > 0) { 119 int g = (int) ((tx / Toolbox.allocation_width) * gradient.stops.size); 120 return_if_fail (0 <= g < gradient.stops.size); 121 current_stop = gradient.stops.get (g); 122 set_color (current_stop.color); 123 } 124 } 125 126 if (selected_bar != 4) { 127 if (update_gradient) { 128 current_stop.color = new Color.hsba (hue, s, b, a); 129 gradient_color_updated (); 130 } else { 131 if (has_stroke_color && stroke_selected) { 132 stroke_color = new Color.hsba (hue, s, b, a); 133 stroke_color_updated (); 134 } else { 135 fill_color = new Color.hsba (hue, s, b, a); 136 fill_color_updated (); 137 } 138 } 139 } 140 } 141 142 public Color get_stroke_color () { 143 return stroke_color; 144 } 145 146 public Color get_fill_color () { 147 return fill_color; 148 } 149 150 public override void draw_tool (Context cr, double px, double py) { 151 draw_bars (cr, px, py); 152 draw_dial (cr, px, py, 0, hue); 153 draw_dial (cr, px, py, 1, s); 154 draw_dial (cr, px, py, 2, b); 155 draw_dial (cr, px, py, 3, a); 156 } 157 158 public void draw_bars (Context cr, double px, double py) { 159 double scale = Toolbox.get_scale (); 160 double step = 1.0 / Toolbox.allocation_width; 161 Color c; 162 double y = this.y - py; 163 164 for (double p = 0; p < 1; p += step) { 165 c = new Color.hsba (p, 1, 1, 1); 166 cr.save (); 167 cr.set_source_rgba (c.r, c.g, c.b, c.a); 168 cr.rectangle (p * Toolbox.allocation_width, y, scale, bar_height); 169 cr.fill (); 170 cr.restore (); 171 172 c = new Color.hsba (hue, p, 1, 1); 173 cr.save (); 174 cr.set_source_rgba (c.r, c.g, c.b, c.a); 175 cr.rectangle (p * Toolbox.allocation_width, y + bar_height, scale, bar_height); 176 cr.fill (); 177 cr.restore (); 178 179 c = new Color.hsba (hue, s, p, 1); 180 cr.save (); 181 cr.set_source_rgba (c.r, c.g, c.b, c.a); 182 cr.rectangle (p * Toolbox.allocation_width, y + 2 * bar_height, scale, bar_height); 183 cr.fill (); 184 cr.restore (); 185 186 c = new Color.hsba (hue, s, b, p); 187 cr.save (); 188 cr.set_source_rgba (c.r, c.g, c.b, c.a); 189 cr.rectangle (p * Toolbox.allocation_width, y + 3 * bar_height, scale, bar_height); 190 cr.fill (); 191 cr.restore (); 192 } 193 194 if (!update_gradient) { 195 if (!has_stroke_color) { 196 c = fill_color; 197 cr.save (); 198 cr.set_source_rgba (c.r, c.g, c.b, c.a); 199 cr.rectangle (0, y + 4 * bar_height, Toolbox.allocation_width, bar_height); 200 cr.fill (); 201 cr.restore (); 202 } else { 203 double cw = Toolbox.allocation_width / 2.0 - 2 * scale; 204 205 cr.save (); 206 cr.set_source_rgba (fill_color.r, fill_color.g, fill_color.b, fill_color.a); 207 cr.rectangle (0, y + 4 * bar_height, cw, bar_height); 208 cr.fill (); 209 cr.restore (); 210 211 cr.save (); 212 cr.set_source_rgba (stroke_color.r, stroke_color.g, stroke_color.b, stroke_color.a); 213 cr.rectangle (cw + 4 * scale, y + 4 * bar_height, cw, bar_height); 214 cr.fill (); 215 cr.restore (); 216 217 if (has_stroke_color) { 218 if (stroke_selected) { 219 cr.save (); 220 Theme.color (cr, "Tool Foreground"); 221 cr.set_line_width (1); 222 cr.rectangle (cw + 4 * scale, y + 4 * bar_height, cw, bar_height); 223 cr.stroke (); 224 cr.restore (); 225 } else { 226 cr.save (); 227 Theme.color (cr, "Tool Foreground"); 228 cr.set_line_width (1); 229 cr.rectangle (0, y + 4 * bar_height, cw, bar_height); 230 cr.stroke (); 231 cr.restore (); 232 } 233 } 234 } 235 } else { // update gradient 236 int stop_size = (int) ((double) Toolbox.allocation_width / gradient.stops.size); 237 for (int i = 0; i < gradient.stops.size; i++) { 238 Stop s = gradient.stops.get (i); 239 c = s.color; 240 cr.save (); 241 cr.set_source_rgba (c.r, c.g, c.b, c.a); 242 cr.rectangle (i * stop_size, y + 4 * bar_height, stop_size, bar_height); 243 cr.fill (); 244 cr.restore (); 245 } 246 247 bool found = false; 248 for (int i = 0; i < gradient.stops.size; i++) { 249 Stop s = gradient.stops.get (i); 250 if (s == current_stop) { 251 found = true; 252 cr.save (); 253 Theme.color (cr, "Tool Foreground"); 254 cr.set_line_width (1); 255 cr.rectangle (i * stop_size, y + 4 * bar_height, stop_size, bar_height); 256 cr.stroke (); 257 cr.restore (); 258 } 259 } 260 261 if (!found) { 262 warning ("No stop selected."); 263 } 264 } 265 266 } 267 268 void draw_dial (Context cr, double px, double py, int bar_index, double val) { 269 double y = this.y - py; 270 double scale = Toolbox.get_scale (); 271 double p; 272 p = bar_index * bar_height; 273 274 return_if_fail (y + p + bar_height - 2 * scale > 0); 275 276 cr.save (); 277 cr.set_line_width (1 * scale); 278 cr.set_source_rgba (1, 1, 1, 1); 279 cr.move_to (val * Toolbox.allocation_width * scale - 3 * scale, y + p + bar_height); 280 cr.line_to (val * Toolbox.allocation_width, y + p + bar_height - 2 * scale); 281 cr.line_to (val * Toolbox.allocation_width + 3 * scale, y + p + bar_height); 282 cr.stroke_preserve (); 283 cr.set_source_rgba (0, 0, 0, 1); 284 cr.fill (); 285 cr.restore (); 286 287 cr.save (); 288 cr.set_line_width (1 * scale); 289 cr.set_source_rgba (1, 1, 1, 1); 290 cr.move_to (val * Toolbox.allocation_width * scale - 3 * scale, y + p); 291 cr.line_to (val * Toolbox.allocation_width, y + p + 2 * scale); 292 cr.line_to (val * Toolbox.allocation_width + 3 * scale, y + p); 293 cr.stroke_preserve (); 294 cr.set_source_rgba (0, 0, 0, 1); 295 cr.fill (); 296 cr.restore (); 297 } 298 } 299 300 } 301