The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

BackgroundTool.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/BackgroundTool.vala.
Speed optimization for rotation of raster images
1 /* 2 Copyright (C) 2012 2014 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 BackgroundTool : Tool { 20 21 double begin_x = 0; 22 double begin_y = 0; 23 24 int last_x; 25 int last_y; 26 27 public double img_offset_x = 0; 28 public double img_offset_y = 0; 29 30 public double img_width = 0; 31 public double img_height = 0; 32 33 public double img_scale_x = 0; 34 35 public static double top_limit; 36 public static double bottom_limit; 37 38 bool move_bg; 39 40 static BackgroundImage imported_background; 41 static ImageSurface imported_surface; 42 43 public BackgroundTool (string name) { 44 base (name, t_("Move, resize and rotate background image")); 45 46 top_limit = 0; 47 bottom_limit = 0; 48 49 imported_background = new BackgroundImage (""); 50 51 select_action.connect((self) => { 52 }); 53 54 deselect_action.connect ((self) => { 55 }); 56 57 press_action.connect((self, b, x, y) => { 58 Glyph g = MainWindow.get_current_glyph (); 59 BackgroundImage? bg = g.get_background_image (); 60 BackgroundImage background; 61 62 if (bg == null) { 63 return; 64 } 65 66 background = (!) bg; 67 68 g.store_undo_state (); 69 70 background.handler_press (x, y); 71 72 begin_x = x; 73 begin_y = y; 74 75 img_offset_x = background.img_offset_x; 76 img_offset_y = background.img_offset_y; 77 78 img_scale_x = background.img_scale_x; 79 80 img_width = background.get_img ().get_width () * background.img_scale_x; 81 img_height = background.get_img ().get_height () * background.img_scale_y; 82 83 move_bg = true; 84 85 last_x = x; 86 last_y = y; 87 }); 88 89 release_action.connect((self, b, x, y) => { 90 Glyph g = MainWindow.get_current_glyph (); 91 BackgroundImage? bg = g.get_background_image (); 92 double coordinate_x, coordinate_y; 93 94 if (bg == null) { 95 return; 96 } 97 98 BackgroundImage background = (!) bg; 99 100 coordinate_x = Glyph.path_coordinate_x (x); 101 coordinate_y = Glyph.path_coordinate_y (y); 102 103 if (background.selected_handle == 2) { 104 background.set_img_rotation_from_coordinate (coordinate_x, coordinate_y); 105 } 106 107 img_offset_x = background.img_offset_x; 108 img_offset_y = background.img_offset_y; 109 110 background.handler_release (x, y); 111 112 move_bg = false; 113 }); 114 115 move_action.connect((self, x, y) => { 116 move (x, y); 117 }); 118 119 key_press_action.connect ((self, keyval) => { 120 move_bg = true; 121 begin_x = 0; 122 begin_y = 0; 123 124 switch (keyval) { 125 case Key.UP: 126 move (0, -1); 127 break; 128 case Key.DOWN: 129 move (0, 1); 130 break; 131 case Key.LEFT: 132 move (-1, 0); 133 break; 134 case Key.RIGHT: 135 move (1, 0); 136 break; 137 default: 138 break; 139 } 140 141 move_bg = false; 142 }); 143 144 145 draw_action.connect ((self, cairo_context, glyph) => { 146 Glyph g = MainWindow.get_current_glyph (); 147 BackgroundImage? background_image = g.get_background_image (); 148 if (background_image == null) return; 149 150 ((!) background_image).draw_handle (cairo_context, glyph); 151 }); 152 } 153 154 void move (int x, int y) { 155 Glyph g = MainWindow.get_current_glyph (); 156 BackgroundImage? background_image = g.get_background_image (); 157 BackgroundImage bg = (!) background_image; 158 double xscale, yscale, dx, dy, xc, yc; 159 double coordinate_x, coordinate_y; 160 double view_zoom; 161 162 if (background_image == null) { 163 return; 164 } 165 166 bg.handler_move (x, y); 167 168 dx = x - begin_x; 169 dy = y - begin_y; 170 171 dx *= 1 / g.view_zoom; 172 dy *= 1 / g.view_zoom; 173 174 dx *= PenTool.precision; 175 dy *= PenTool.precision; 176 177 if (bg.selected_handle == 2) { 178 coordinate_x = Glyph.path_coordinate_x (x); 179 coordinate_y = Glyph.path_coordinate_y (y); 180 view_zoom = MainWindow.get_current_glyph ().view_zoom; 181 bg.preview_img_rotation_from_coordinate (coordinate_x, coordinate_y, view_zoom); 182 } 183 184 if (bg.selected_handle == 1) { 185 xscale = img_scale_x * ((img_width - dx) / img_width); 186 yscale = xscale; 187 188 xc = bg.img_middle_x; 189 yc = bg.img_middle_y; 190 191 bg.set_img_scale (xscale, yscale); 192 193 bg.img_middle_x = xc; 194 bg.img_middle_y = yc; 195 } 196 197 if (move_bg && bg.selected_handle <= 0) { 198 bg.set_img_offset (this.img_offset_x + dx, this.img_offset_y + dy); 199 } 200 201 GlyphCanvas.redraw (); 202 203 last_x = x; 204 last_y = y; 205 } 206 207 public static void load_background_image () { 208 // generate png file if needed and load the image with cairo 209 imported_surface = imported_background.get_img (); 210 211 IdleSource idle = new IdleSource (); 212 idle.set_callback (() => { 213 TabBar tb = MainWindow.get_tab_bar (); 214 Glyph g = MainWindow.get_current_glyph (); 215 216 g.set_background_image (imported_background); 217 imported_background.center_in_glyph (); 218 219 Toolbox.select_tool_by_name ("zoom_background_image"); 220 tb.select_tab_name (g.get_name ()); 221 Toolbox.select_tool_by_name ("cut_background"); 222 223 GlyphCanvas.redraw (); 224 return false; 225 }); 226 idle.attach (null); 227 } 228 229 internal static void import_background_image () { 230 FileChooser fc = new FileChooser (); 231 232 fc.file_selected.connect ((fn) => { 233 BackgroundImage bg; 234 string path; 235 236 if (fn != null) { 237 path = (!) fn; 238 bg = new BackgroundImage (path); 239 imported_background = bg; 240 MainWindow.native_window.load_background_image (); 241 } 242 }); 243 244 MainWindow.file_chooser (t_("Select background image"), fc, FileChooser.LOAD); 245 } 246 } 247 248 } 249