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