Merge lp:~mw-triad/inkscape/polygonal-grid into lp:~inkscape.dev/inkscape/trunk
- polygonal-grid
- Merge into trunk
Status: | Needs review | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~mw-triad/inkscape/polygonal-grid | ||||
Merge into: | lp:~inkscape.dev/inkscape/trunk | ||||
Diff against target: |
1118 lines (+938/-17) (has conflicts) 8 files modified
src/display/CMakeLists.txt (+1/-0) src/display/canvas-grid.cpp (+33/-2) src/display/canvas-grid.h (+3/-2) src/display/canvas-ngongrid.cpp (+747/-0) src/display/canvas-ngongrid.h (+94/-0) src/ui/dialog/document-properties.cpp (+2/-0) src/ui/dialog/inkscape-preferences.cpp (+46/-13) src/ui/dialog/inkscape-preferences.h (+12/-0) Text conflict in src/display/canvas-grid.cpp Text conflict in src/ui/dialog/inkscape-preferences.cpp |
||||
To merge this branch: | bzr merge lp:~mw-triad/inkscape/polygonal-grid | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
jazzynico (community) | Needs Fixing | ||
Review via email: mp+293349@code.launchpad.net |
Commit message
Description of the change
Generating diff against the current trunk.
Unmerged revisions
- 11944. By Matthew Woehlke
-
fix wrong snap for grid origin != (0, 0)
Fix missing addition of grid offset, causing broken snapping to
polygonal grid when grid origin is not (0, 0). - 11943. By Matthew Woehlke
-
implement polygonal grid snapping
Add necessary code to find the nearest relevant lines to which to snap
for the polygonal grid. - 11942. By Matthew Woehlke
-
auto-extents improvements
Compute minimum X extent so we don't render concentric segments that
aren't needed. Add note that we could do better skipping sections that
won't be visible. - 11941. By Matthew Woehlke
-
fix polygonal grid extents
Hook up polygonal grid extents calculation so that we always draw enough
grid to fill the viewport, rather than truncating the grid at an
arbitrary point. - 11940. By Matthew Woehlke
-
start implementing polygonal grid renderingg
Implement basic rendering for the polygonal grid. For now, this uses an
arbitrary max extent (rather than determining max extents per section
with respect to the viewport), and doesn't attempt to clip grid lines to
the viewport. Also, snapping is not yet implemented (the old code from
the axonometric grid has been commented out for now). - 11939. By Matthew Woehlke
-
implement UI for polygonal grid
Modify the UI for polygonal grid to have the appropriate parameters,
rather than those copied from axonometric grid. Since the grid logic has
not been changed yet, we are using the rotation angle as both angles for
the axonometric logic (which gives a degenerate grid with the default
value 0). - 11938. By Matthew Woehlke
-
add template for polygonal grid
Create new 'polygonal' grid type. Right now this is just a copy of the
axonometric grid type, to get the necessary bits in place before
starting to develop the actual logic. - 11937. By Matthew Woehlke
-
whitespace fix
Preview Diff
1 | === modified file 'src/display/CMakeLists.txt' |
2 | --- src/display/CMakeLists.txt 2015-12-10 05:43:23 +0000 |
3 | +++ src/display/CMakeLists.txt 2016-04-29 07:04:20 +0000 |
4 | @@ -5,6 +5,7 @@ |
5 | canvas-axonomgrid.cpp |
6 | canvas-bpath.cpp |
7 | canvas-grid.cpp |
8 | + canvas-ngongrid.cpp |
9 | canvas-temporary-item-list.cpp |
10 | canvas-temporary-item.cpp |
11 | canvas-text.cpp |
12 | |
13 | === modified file 'src/display/canvas-grid.cpp' |
14 | --- src/display/canvas-grid.cpp 2015-05-06 11:55:31 +0000 |
15 | +++ src/display/canvas-grid.cpp 2016-04-29 07:04:20 +0000 |
16 | @@ -36,6 +36,7 @@ |
17 | #include "display/cairo-utils.h" |
18 | #include "display/canvas-axonomgrid.h" |
19 | #include "display/canvas-grid.h" |
20 | +#include "display/canvas-ngongrid.h" |
21 | #include "display/sp-canvas-group.h" |
22 | #include "document.h" |
23 | #include "util/units.h" |
24 | @@ -58,11 +59,13 @@ |
25 | |
26 | static gchar const *const grid_name[] = { |
27 | N_("Rectangular grid"), |
28 | - N_("Axonometric grid") |
29 | + N_("Axonometric grid"), |
30 | + N_("Polygonal grid") |
31 | }; |
32 | static gchar const *const grid_svgname[] = { |
33 | "xygrid", |
34 | - "axonomgrid" |
35 | + "axonomgrid", |
36 | + "ngongrid" |
37 | }; |
38 | |
39 | |
40 | @@ -72,7 +75,33 @@ |
41 | static void grid_canvasitem_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); |
42 | static void grid_canvasitem_render (SPCanvasItem *item, SPCanvasBuf *buf); |
43 | |
44 | +<<<<<<< TREE |
45 | G_DEFINE_TYPE(GridCanvasItem, grid_canvasitem, SP_TYPE_CANVAS_ITEM); |
46 | +======= |
47 | +static SPCanvasItemClass * parent_class; |
48 | + |
49 | +GType |
50 | +grid_canvasitem_get_type (void) |
51 | +{ |
52 | + static GType grid_canvasitem_type = 0; |
53 | + |
54 | + if (!grid_canvasitem_type) { |
55 | + GTypeInfo grid_canvasitem_info = { |
56 | + sizeof (GridCanvasItemClass), |
57 | + NULL, NULL, |
58 | + (GClassInitFunc) grid_canvasitem_class_init, |
59 | + NULL, NULL, |
60 | + sizeof (GridCanvasItem), |
61 | + 0, |
62 | + (GInstanceInitFunc) grid_canvasitem_init, |
63 | + NULL |
64 | + }; |
65 | + |
66 | + grid_canvasitem_type = g_type_register_static(SPCanvasItem::getType(), "GridCanvasItem", &grid_canvasitem_info, GTypeFlags(0)); |
67 | + } |
68 | + return grid_canvasitem_type; |
69 | +} |
70 | +>>>>>>> MERGE-SOURCE |
71 | |
72 | static void grid_canvasitem_class_init(GridCanvasItemClass *klass) |
73 | { |
74 | @@ -263,6 +292,8 @@ |
75 | return dynamic_cast<CanvasGrid*>(new CanvasXYGrid(nv, repr, doc)); |
76 | case GRID_AXONOMETRIC: |
77 | return dynamic_cast<CanvasGrid*>(new CanvasAxonomGrid(nv, repr, doc)); |
78 | + case GRID_POLYGONAL: |
79 | + return dynamic_cast<CanvasGrid*>(new CanvasNGonGrid(nv, repr, doc)); |
80 | } |
81 | |
82 | return NULL; |
83 | |
84 | === modified file 'src/display/canvas-grid.h' |
85 | --- src/display/canvas-grid.h 2014-10-08 02:22:03 +0000 |
86 | +++ src/display/canvas-grid.h 2016-04-29 07:04:20 +0000 |
87 | @@ -34,9 +34,10 @@ |
88 | |
89 | enum GridType { |
90 | GRID_RECTANGULAR = 0, |
91 | - GRID_AXONOMETRIC = 1 |
92 | + GRID_AXONOMETRIC = 1, |
93 | + GRID_POLYGONAL = 2 |
94 | }; |
95 | -#define GRID_MAXTYPENR 1 |
96 | +#define GRID_MAXTYPENR 2 |
97 | |
98 | #define INKSCAPE_TYPE_GRID_CANVASITEM (Inkscape::grid_canvasitem_get_type ()) |
99 | #define INKSCAPE_GRID_CANVASITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INKSCAPE_TYPE_GRID_CANVASITEM, GridCanvasItem)) |
100 | |
101 | === added file 'src/display/canvas-ngongrid.cpp' |
102 | --- src/display/canvas-ngongrid.cpp 1970-01-01 00:00:00 +0000 |
103 | +++ src/display/canvas-ngongrid.cpp 2016-04-29 07:04:20 +0000 |
104 | @@ -0,0 +1,747 @@ |
105 | +/* |
106 | + * Authors: |
107 | + * Matthew Woehlke <mw_triad@users.sourceforge.net> |
108 | + * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl> |
109 | + * |
110 | + * Copyright (C) 2006-2012 Authors |
111 | + * Released under GNU GPL, read the file 'COPYING' for more information |
112 | + */ |
113 | + |
114 | + /* |
115 | + * Current limits are: one axis (y-axis) is always vertical. The other two |
116 | + * axes are bound to a certain range of angles. The z-axis always has an angle |
117 | + * smaller than 90 degrees (measured from horizontal, 0 degrees being a line extending |
118 | + * to the right). The x-axis will always have an angle between 0 and 90 degrees. |
119 | + */ |
120 | + |
121 | + |
122 | +#include <gtkmm/box.h> |
123 | +#include <gtkmm/label.h> |
124 | +#include <gtkmm/table.h> |
125 | +#include <glibmm/i18n.h> |
126 | + |
127 | +#include "display/canvas-ngongrid.h" |
128 | + |
129 | +#include "ui/widget/registered-widget.h" |
130 | +#include "desktop.h" |
131 | +#include "desktop-handles.h" |
132 | +#include "display/cairo-utils.h" |
133 | +#include "display/canvas-grid.h" |
134 | +#include "display/sp-canvas-util.h" |
135 | +#include "display/sp-canvas.h" |
136 | +#include "document.h" |
137 | +#include "inkscape.h" |
138 | +#include "preferences.h" |
139 | +#include "sp-namedview.h" |
140 | +#include "sp-object.h" |
141 | +#include "svg/svg-color.h" |
142 | +#include "2geom/line.h" |
143 | +#include "2geom/angle.h" |
144 | +#include "util/mathfns.h" |
145 | +#include "round.h" |
146 | +#include "helper/units.h" |
147 | + |
148 | + |
149 | +/** |
150 | + * This function calls Cairo to render a line on a particular canvas buffer. |
151 | + * Coordinates are interpreted as SCREENcoordinates |
152 | + */ |
153 | +static void |
154 | +sp_cngongrid_drawline (SPCanvasBuf *buf, gdouble x0, gdouble y0, gdouble x1, gdouble y1, guint32 rgba) |
155 | +{ |
156 | + // Prevent aliasing of horizontal/vertical lines |
157 | + if (Geom::are_near(x0, x1)) { |
158 | + x0 = round(x0); |
159 | + x1 = round(x1); |
160 | + } |
161 | + if (Geom::are_near(y0, y1)) { |
162 | + y0 = round(y0); |
163 | + y1 = round(y1); |
164 | + } |
165 | + //TODO: clip to viewport? |
166 | + cairo_move_to(buf->ct, 0.5 + x0, 0.5 + y0); |
167 | + cairo_line_to(buf->ct, 0.5 + x1, 0.5 + y1); |
168 | + ink_cairo_set_source_rgba32(buf->ct, rgba); |
169 | + cairo_stroke(buf->ct); |
170 | +} |
171 | + |
172 | +static gdouble |
173 | +distance(gdouble x, gdouble y, double dx, double dy) |
174 | +{ |
175 | + return (dy * x) - (dx * y); |
176 | +} |
177 | + |
178 | +static gdouble |
179 | +find_bound(Geom::Rect const &rect, double dx, double dy, gdouble const & (*bound_func)(gdouble const &, gdouble const &)) |
180 | +{ |
181 | + // Note: Y+ is DOWN, not up! |
182 | + if ( (dx > 0.0) == (dy > 0.0) ) { // Interesting points are bottom-left, top-right |
183 | + gdouble const a = distance(rect.left(), rect.bottom(), dx, dy); |
184 | + gdouble const b = distance(rect.right(), rect.top(), dx, dy); |
185 | + return bound_func(a, b); |
186 | + } else { // Interesting points are top-left, bottom-right |
187 | + gdouble const a = distance(rect.left(), rect.top(), dx, dy); |
188 | + gdouble const b = distance(rect.right(), rect.bottom(), dx, dy); |
189 | + return bound_func(a, b); |
190 | + } |
191 | +} |
192 | + |
193 | +namespace Inkscape { |
194 | + |
195 | + |
196 | +/** |
197 | +* A DIRECT COPY-PASTE FROM DOCUMENT-PROPERTIES.CPP TO QUICKLY GET RESULTS |
198 | +* |
199 | + * Helper function that attachs widgets in a 3xn table. The widgets come in an |
200 | + * array that has two entries per table row. The two entries code for four |
201 | + * possible cases: (0,0) means insert space in first column; (0, non-0) means |
202 | + * widget in columns 2-3; (non-0, 0) means label in columns 1-3; and |
203 | + * (non-0, non-0) means two widgets in columns 2 and 3. |
204 | +**/ |
205 | +#define SPACE_SIZE_X 15 |
206 | +#define SPACE_SIZE_Y 10 |
207 | +static inline void |
208 | +attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], unsigned size, int start = 0) |
209 | +{ |
210 | + for (unsigned i=0, r=start; i<size/sizeof(Gtk::Widget*); i+=2) { |
211 | + if (arr[i] && arr[i+1]) { |
212 | + table.attach (const_cast<Gtk::Widget&>(*arr[i]), 1, 2, r, r+1, |
213 | + Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); |
214 | + table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 2, 3, r, r+1, |
215 | + Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); |
216 | + } else { |
217 | + if (arr[i+1]) { |
218 | + table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 1, 3, r, r+1, |
219 | + Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); |
220 | + } else if (arr[i]) { |
221 | + Gtk::Label& label = reinterpret_cast<Gtk::Label&> (const_cast<Gtk::Widget&>(*arr[i])); |
222 | + label.set_alignment (0.0); |
223 | + table.attach (label, 0, 3, r, r+1, |
224 | + Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); |
225 | + } else { |
226 | + Gtk::HBox *space = manage (new Gtk::HBox); |
227 | + space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y); |
228 | + table.attach (*space, 0, 1, r, r+1, |
229 | + (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0); |
230 | + } |
231 | + } |
232 | + ++r; |
233 | + } |
234 | +} |
235 | + |
236 | +CanvasNGonGrid::CanvasNGonGrid (SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc) |
237 | + : CanvasGrid(nv, in_repr, in_doc, GRID_POLYGONAL) |
238 | +{ |
239 | + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
240 | + gridunit = sp_unit_get_by_abbreviation( prefs->getString("/options/grids/ngon/units").data() ); |
241 | + if (!gridunit) |
242 | + gridunit = &sp_unit_get_by_id(SP_UNIT_PX); |
243 | + origin[Geom::X] = sp_units_get_pixels( prefs->getDouble("/options/grids/ngon/origin_x", 0.0), *gridunit ); |
244 | + origin[Geom::Y] = sp_units_get_pixels( prefs->getDouble("/options/grids/ngon/origin_y", 0.0), *gridunit ); |
245 | + sections = prefs->getInt("/options/grids/ngon/sect_n", 8); |
246 | + lengthx = sp_units_get_pixels( prefs->getDouble("/options/grids/ngon/spacing_x", 1.0), *gridunit ); |
247 | + lengthy = sp_units_get_pixels( prefs->getDouble("/options/grids/ngon/spacing_y", 1.0), *gridunit ); |
248 | + angle_deg = prefs->getDouble("/options/grids/ngon/rotation", 0.0); |
249 | + color = prefs->getInt("/options/grids/ngon/color", 0x0000ff20); |
250 | + empcolor = prefs->getInt("/options/grids/ngon/empcolor", 0x0000ff40); |
251 | + empspacing = prefs->getInt("/options/grids/ngon/empspacing", 5); |
252 | + |
253 | + angle_rad = Geom::deg_to_rad(angle_deg); |
254 | + se_angle_deg = 180.0 / sections; |
255 | + se_angle_rad = Geom::deg_to_rad(se_angle_deg); |
256 | + se_tan = tan(se_angle_rad); |
257 | + |
258 | + snapper = new CanvasNGonGridSnapper(this, &namedview->snap_manager, 0); |
259 | + |
260 | + if (repr) readRepr(); |
261 | +} |
262 | + |
263 | +CanvasNGonGrid::~CanvasNGonGrid () |
264 | +{ |
265 | + if (snapper) delete snapper; |
266 | +} |
267 | + |
268 | + |
269 | +/* fixme: Collect all these length parsing methods and think common sane API */ |
270 | + |
271 | +static gboolean sp_nv_read_length(gchar const *str, guint base, gdouble *val, SPUnit const **unit) |
272 | +{ |
273 | + if (!str) { |
274 | + return FALSE; |
275 | + } |
276 | + |
277 | + gchar *u; |
278 | + gdouble v = g_ascii_strtod(str, &u); |
279 | + if (!u) { |
280 | + return FALSE; |
281 | + } |
282 | + while (isspace(*u)) { |
283 | + u += 1; |
284 | + } |
285 | + |
286 | + if (!*u) { |
287 | + /* No unit specified - keep default */ |
288 | + *val = v; |
289 | + return TRUE; |
290 | + } |
291 | + |
292 | + if (base & SP_UNIT_DEVICE) { |
293 | + if (u[0] && u[1] && !isalnum(u[2]) && !strncmp(u, "px", 2)) { |
294 | + *unit = &sp_unit_get_by_id(SP_UNIT_PX); |
295 | + *val = v; |
296 | + return TRUE; |
297 | + } |
298 | + } |
299 | + |
300 | + if (base & SP_UNIT_ABSOLUTE) { |
301 | + if (!strncmp(u, "pt", 2)) { |
302 | + *unit = &sp_unit_get_by_id(SP_UNIT_PT); |
303 | + } else if (!strncmp(u, "mm", 2)) { |
304 | + *unit = &sp_unit_get_by_id(SP_UNIT_MM); |
305 | + } else if (!strncmp(u, "cm", 2)) { |
306 | + *unit = &sp_unit_get_by_id(SP_UNIT_CM); |
307 | + } else if (!strncmp(u, "m", 1)) { |
308 | + *unit = &sp_unit_get_by_id(SP_UNIT_M); |
309 | + } else if (!strncmp(u, "in", 2)) { |
310 | + *unit = &sp_unit_get_by_id(SP_UNIT_IN); |
311 | + } else if (!strncmp(u, "ft", 2)) { |
312 | + *unit = &sp_unit_get_by_id(SP_UNIT_FT); |
313 | + } else if (!strncmp(u, "pc", 2)) { |
314 | + *unit = &sp_unit_get_by_id(SP_UNIT_PC); |
315 | + } else { |
316 | + return FALSE; |
317 | + } |
318 | + *val = v; |
319 | + return TRUE; |
320 | + } |
321 | + |
322 | + return FALSE; |
323 | +} |
324 | + |
325 | +static gboolean sp_nv_read_opacity(gchar const *str, guint32 *color) |
326 | +{ |
327 | + if (!str) { |
328 | + return FALSE; |
329 | + } |
330 | + |
331 | + gchar *u; |
332 | + gdouble v = g_ascii_strtod(str, &u); |
333 | + if (!u) { |
334 | + return FALSE; |
335 | + } |
336 | + v = CLAMP(v, 0.0, 1.0); |
337 | + |
338 | + *color = (*color & 0xffffff00) | (guint32) floor(v * 255.9999); |
339 | + |
340 | + return TRUE; |
341 | +} |
342 | + |
343 | + |
344 | + |
345 | +void |
346 | +CanvasNGonGrid::readRepr() |
347 | +{ |
348 | + gchar const *value; |
349 | + if ( (value = repr->attribute("originx")) ) { |
350 | + sp_nv_read_length(value, SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE, &origin[Geom::X], &gridunit); |
351 | + origin[Geom::X] = sp_units_get_pixels(origin[Geom::X], *(gridunit)); |
352 | + } |
353 | + if ( (value = repr->attribute("originy")) ) { |
354 | + sp_nv_read_length(value, SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE, &origin[Geom::Y], &gridunit); |
355 | + origin[Geom::Y] = sp_units_get_pixels(origin[Geom::Y], *(gridunit)); |
356 | + } |
357 | + |
358 | + if ( (value = repr->attribute("sections")) ) { |
359 | + sections = atoi(value); |
360 | + if (sections < 3) sections = 3; |
361 | + if (sections > 360) sections = 360; |
362 | + se_angle_deg = 180.0 / sections; |
363 | + se_angle_rad = Geom::deg_to_rad(se_angle_deg); |
364 | + se_tan = tan(se_angle_rad); |
365 | + } |
366 | + |
367 | + if ( (value = repr->attribute("spacingx")) ) { |
368 | + sp_nv_read_length(value, SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE, &lengthx, &gridunit); |
369 | + lengthx = sp_units_get_pixels(lengthx, *(gridunit)); |
370 | + if (lengthx < 0.0500) lengthx = 0.0500; |
371 | + } |
372 | + |
373 | + if ( (value = repr->attribute("spacingy")) ) { |
374 | + sp_nv_read_length(value, SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE, &lengthy, &gridunit); |
375 | + lengthy = sp_units_get_pixels(lengthy, *(gridunit)); |
376 | + if (lengthy < 0.0500) lengthy = 0.0500; |
377 | + } |
378 | + |
379 | + if ( (value = repr->attribute("rotation")) ) { |
380 | + angle_deg = g_ascii_strtod(value, NULL); |
381 | + double max_angle = 360.0 / sections; |
382 | + if (fabs(angle_deg) > max_angle) angle_deg = fmod(angle_deg, max_angle); |
383 | + angle_rad = Geom::deg_to_rad(angle_deg); |
384 | + } |
385 | + |
386 | + if ( (value = repr->attribute("color")) ) { |
387 | + color = (color & 0xff) | sp_svg_read_color(value, color); |
388 | + } |
389 | + |
390 | + if ( (value = repr->attribute("empcolor")) ) { |
391 | + empcolor = (empcolor & 0xff) | sp_svg_read_color(value, empcolor); |
392 | + } |
393 | + |
394 | + if ( (value = repr->attribute("opacity")) ) { |
395 | + sp_nv_read_opacity(value, &color); |
396 | + } |
397 | + if ( (value = repr->attribute("empopacity")) ) { |
398 | + sp_nv_read_opacity(value, &empcolor); |
399 | + } |
400 | + |
401 | + if ( (value = repr->attribute("empspacing")) ) { |
402 | + empspacing = atoi(value); |
403 | + } |
404 | + |
405 | + if ( (value = repr->attribute("visible")) ) { |
406 | + visible = (strcmp(value,"false") != 0 && strcmp(value, "0") != 0); |
407 | + } |
408 | + |
409 | + if ( (value = repr->attribute("enabled")) ) { |
410 | + g_assert(snapper != NULL); |
411 | + snapper->setEnabled(strcmp(value,"false") != 0 && strcmp(value, "0") != 0); |
412 | + } |
413 | + |
414 | + if ( (value = repr->attribute("snapvisiblegridlinesonly")) ) { |
415 | + g_assert(snapper != NULL); |
416 | + snapper->setSnapVisibleOnly(strcmp(value,"false") != 0 && strcmp(value, "0") != 0); |
417 | + } |
418 | + |
419 | + for (GSList *l = canvasitems; l != NULL; l = l->next) { |
420 | + sp_canvas_item_request_update ( SP_CANVAS_ITEM(l->data) ); |
421 | + } |
422 | + return; |
423 | +} |
424 | + |
425 | +/** |
426 | + * Called when XML node attribute changed; updates dialog widgets if change was not done by widgets themselves. |
427 | + */ |
428 | +void |
429 | +CanvasNGonGrid::onReprAttrChanged(Inkscape::XML::Node */*repr*/, gchar const */*key*/, gchar const */*oldval*/, gchar const */*newval*/, bool /*is_interactive*/) |
430 | +{ |
431 | + readRepr(); |
432 | + |
433 | + if ( ! (_wr.isUpdating()) ) |
434 | + updateWidgets(); |
435 | +} |
436 | + |
437 | + |
438 | + |
439 | + |
440 | +Gtk::Widget * |
441 | +CanvasNGonGrid::newSpecificWidget() |
442 | +{ |
443 | + Gtk::Table * table = Gtk::manage( new Gtk::Table(1,1) ); |
444 | + table->set_spacings(2); |
445 | + |
446 | +_wr.setUpdating (true); |
447 | + |
448 | + Inkscape::UI::Widget::RegisteredUnitMenu *_rumg = Gtk::manage( new Inkscape::UI::Widget::RegisteredUnitMenu( |
449 | + _("Grid _units:"), "units", _wr, repr, doc) ); |
450 | + Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_ox = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalarUnit( |
451 | + _("_Origin X:"), _("X coordinate of grid origin"), "originx", *_rumg, _wr, repr, doc) ); |
452 | + Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_oy = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalarUnit( |
453 | + _("O_rigin Y:"), _("Y coordinate of grid origin"), "originy", *_rumg, _wr, repr, doc) ); |
454 | + Inkscape::UI::Widget::RegisteredScalar *_rsu_ns = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalar( |
455 | + _("_Number of sections:"), "", "sections", _wr, repr, doc ) ); |
456 | + Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_sx = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalarUnit( |
457 | + _("Spacing _X:"), _("Distance between concentric grid polygons"), "spacingx", *_rumg, _wr, repr, doc) ); |
458 | + Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_sy = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalarUnit( |
459 | + _("Spacing _Y:"), _("Distance between semi-radial grid lines"), "spacingy", *_rumg, _wr, repr, doc) ); |
460 | + Inkscape::UI::Widget::RegisteredScalar *_rsu_ar = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalar( |
461 | + _("Ro_tation:"), _("Angle of axis rotation"), "rotation", _wr, repr, doc ) ); |
462 | + |
463 | + Inkscape::UI::Widget::RegisteredColorPicker *_rcp_gcol = Gtk::manage( |
464 | + new Inkscape::UI::Widget::RegisteredColorPicker( |
465 | + _("Minor grid line _color:"), _("Minor grid line color"), _("Color of the minor grid lines"), |
466 | + "color", "opacity", _wr, repr, doc)); |
467 | + |
468 | + Inkscape::UI::Widget::RegisteredColorPicker *_rcp_gmcol = Gtk::manage( |
469 | + new Inkscape::UI::Widget::RegisteredColorPicker( |
470 | + _("Ma_jor grid line color:"), _("Major grid line color"), |
471 | + _("Color of the major (highlighted) grid lines"), |
472 | + "empcolor", "empopacity", _wr, repr, doc)); |
473 | + |
474 | + Inkscape::UI::Widget::RegisteredSuffixedInteger *_rsi = Gtk::manage( new Inkscape::UI::Widget::RegisteredSuffixedInteger( |
475 | + _("_Major grid line every:"), "", _("lines"), "empspacing", _wr, repr, doc ) ); |
476 | + |
477 | + _rsu_ox->setDigits(5); |
478 | + _rsu_ox->setIncrements(0.1, 1.0); |
479 | + |
480 | + _rsu_oy->setDigits(5); |
481 | + _rsu_oy->setIncrements(0.1, 1.0); |
482 | + |
483 | + _rsu_ns->setDigits(0); |
484 | + _rsu_ns->setIncrements(1, 3); |
485 | + |
486 | + _rsu_sx->setDigits(5); |
487 | + _rsu_sx->setIncrements(0.1, 1.0); |
488 | + |
489 | + _rsu_sy->setDigits(5); |
490 | + _rsu_sy->setIncrements(0.1, 1.0); |
491 | + |
492 | + _rsu_ar->setDigits(5); |
493 | + _rsu_ar->setIncrements(0.5, 5.0); |
494 | + |
495 | +_wr.setUpdating (false); |
496 | + |
497 | + Gtk::Widget const *const widget_array[] = { |
498 | + 0, _rumg, |
499 | + 0, _rsu_ox, |
500 | + 0, _rsu_oy, |
501 | + 0, _rsu_ns, |
502 | + 0, _rsu_sx, |
503 | + 0, _rsu_sy, |
504 | + 0, _rsu_ar, |
505 | + _rcp_gcol->_label, _rcp_gcol, |
506 | + 0, 0, |
507 | + _rcp_gmcol->_label, _rcp_gmcol, |
508 | + 0, _rsi, |
509 | + }; |
510 | + |
511 | + attach_all (*table, widget_array, sizeof(widget_array)); |
512 | + |
513 | + // set widget values |
514 | + _rumg->setUnit (gridunit); |
515 | + |
516 | + gdouble val; |
517 | + val = origin[Geom::X]; |
518 | + val = sp_pixels_get_units (val, *(gridunit)); |
519 | + _rsu_ox->setValue (val); |
520 | + val = origin[Geom::Y]; |
521 | + val = sp_pixels_get_units (val, *(gridunit)); |
522 | + _rsu_oy->setValue (val); |
523 | + _rsu_ns->setValue (sections); |
524 | + val = lengthx; |
525 | + double gridx = sp_pixels_get_units (val, *(gridunit)); |
526 | + _rsu_sx->setValue (gridx); |
527 | + val = lengthy; |
528 | + double gridy = sp_pixels_get_units (val, *(gridunit)); |
529 | + _rsu_sy->setValue (gridy); |
530 | + |
531 | + _rsu_ar->setValue(angle_deg); |
532 | + |
533 | + _rcp_gcol->setRgba32 (color); |
534 | + _rcp_gmcol->setRgba32 (empcolor); |
535 | + _rsi->setValue (empspacing); |
536 | + |
537 | + return table; |
538 | +} |
539 | + |
540 | + |
541 | +/** |
542 | + * Update dialog widgets from object's values. |
543 | + */ |
544 | +void |
545 | +CanvasNGonGrid::updateWidgets() |
546 | +{ |
547 | +/* if (_wr.isUpdating()) return; |
548 | + |
549 | + _wr.setUpdating (true); |
550 | + |
551 | + _rcb_visible.setActive(visible); |
552 | + if (snapper != NULL) { |
553 | + _rcb_enabled.setActive(snapper->getEnabled()); |
554 | + } |
555 | + |
556 | + _rumg.setUnit (gridunit); |
557 | + |
558 | + gdouble val; |
559 | + val = origin[Geom::X]; |
560 | + val = sp_pixels_get_units (val, *(gridunit)); |
561 | + _rsu_ox->setValue (val); |
562 | + val = origin[Geom::Y]; |
563 | + val = sp_pixels_get_units (val, *(gridunit)); |
564 | + _rsu_oy->setValue (val); |
565 | + val = lengthx; |
566 | + double gridx = sp_pixels_get_units (val, *(gridunit)); |
567 | + _rsu_sx->setValue (gridx); |
568 | + val = lengthy; |
569 | + double gridy = sp_pixels_get_units (val, *(gridunit)); |
570 | + _rsu_sy->setValue (gridy); |
571 | + |
572 | + _rsu_ar->setValue(angle_deg); |
573 | + |
574 | + _rcp_gcol->setRgba32 (color); |
575 | + _rcp_gmcol->setRgba32 (empcolor); |
576 | + _rsi->setValue (empspacing); |
577 | + |
578 | + _wr.setUpdating (false); |
579 | + |
580 | + return; |
581 | + */ |
582 | +} |
583 | + |
584 | + |
585 | + |
586 | +void |
587 | +CanvasNGonGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/) |
588 | +{ |
589 | + ow = origin * affine; |
590 | + sw = Geom::Point(fabs(affine[0]),fabs(affine[3])); |
591 | + sw[Geom::X] *= lengthx; |
592 | + sw[Geom::Y] *= lengthy; |
593 | + |
594 | + scaled = false; |
595 | + |
596 | + for(int dim = 0; dim < 2; dim++) { |
597 | + gint scaling_factor = empspacing; |
598 | + |
599 | + if (scaling_factor <= 1) |
600 | + scaling_factor = 5; |
601 | + |
602 | + int watchdog = 0; |
603 | + while ( (sw[dim] < 8.0) & (watchdog < 100) ) { |
604 | + scaled = true; |
605 | + sw[dim] *= scaling_factor; |
606 | + // First pass, go up to the major line spacing, then |
607 | + // keep increasing by two. |
608 | + scaling_factor = 2; |
609 | + watchdog++; |
610 | + } |
611 | + |
612 | + } |
613 | + |
614 | + lxw = sw[Geom::X]; |
615 | + lyw = sw[Geom::Y]; |
616 | + |
617 | + if (empspacing == 0) { |
618 | + scaled = true; |
619 | + } |
620 | +} |
621 | + |
622 | +void |
623 | +CanvasNGonGrid::Render (SPCanvasBuf *buf) |
624 | +{ |
625 | + //set correct coloring, depending preference (when zoomed out, always major coloring or minor coloring) |
626 | + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
627 | + guint32 _empcolor; |
628 | + bool preference = prefs->getBool("/options/grids/no_emphasize_when_zoomedout", false); |
629 | + if( scaled && preference ) { |
630 | + _empcolor = color; |
631 | + } else { |
632 | + _empcolor = empcolor; |
633 | + } |
634 | + |
635 | + cairo_save(buf->ct); |
636 | + cairo_translate(buf->ct, -buf->rect.left(), -buf->rect.top()); |
637 | + cairo_set_line_width(buf->ct, 1.0); |
638 | + cairo_set_line_cap(buf->ct, CAIRO_LINE_CAP_SQUARE); |
639 | + |
640 | + double angle_step = 360.0 / sections; |
641 | + for (int s = 0; s < sections; ++s) { |
642 | + //TODO: get angles from origin to viewport corners, use to test if section needs to be rendered |
643 | + renderSection(buf, (s * angle_step) - angle_deg, _empcolor); |
644 | + } |
645 | + |
646 | + cairo_restore(buf->ct); |
647 | +} |
648 | + |
649 | +void |
650 | +CanvasNGonGrid::renderSection (SPCanvasBuf *buf, double section_angle_deg, guint32 _empcolor) |
651 | +{ |
652 | + // pc = preimagecoordinates (the coordinates of the section before rotation) |
653 | + // gc = gridcoordinates (the coordinates calculated from the grids origin 'grid->ow') |
654 | + |
655 | + Geom::Rect buf_gc(buf->rect); |
656 | + buf_gc -= ow; |
657 | + |
658 | + double const section_angle_rad = Geom::deg_to_rad(section_angle_deg); |
659 | + double const section_sin = sin(section_angle_rad); |
660 | + double const section_cos = cos(section_angle_rad); |
661 | + |
662 | + gdouble xmin = find_bound(buf_gc, -section_sin, section_cos, &std::min) / lxw; |
663 | + gdouble xmax = find_bound(buf_gc, -section_sin, section_cos, &std::max) / lxw; |
664 | + if (xmax <= 0) return; // Section is entirely out of viewport |
665 | + |
666 | + gdouble ymin = find_bound(buf_gc, -section_cos, -section_sin, &std::min) / lyw; |
667 | + gdouble ymax = find_bound(buf_gc, -section_cos, -section_sin, &std::max) / lyw; |
668 | + |
669 | + gdouble const lxmax = xmax * lxw; |
670 | + gdouble const xbound = (floor(xmax) + 0.5) * lxw; |
671 | + gdouble const ybound = (floor(ymax) + 0.5) * lyw; |
672 | + |
673 | + // Render section edge line |
674 | + { |
675 | + gdouble const pc_x = lxmax; |
676 | + gdouble const pc_y = lxmax * se_tan; |
677 | + gdouble const gc_x1 = ( (pc_x * section_cos) - (pc_y * section_sin) ) + ow[Geom::X]; |
678 | + gdouble const gc_y1 = ( (pc_x * section_sin) + (pc_y * section_cos) ) + ow[Geom::Y]; |
679 | + sp_cngongrid_drawline (buf, ow[Geom::X], ow[Geom::Y], gc_x1, gc_y1, color); |
680 | + } |
681 | + |
682 | + // Render semi-radius lines |
683 | + ymin = ceil(ymin); |
684 | + gint xlinenum = ymin; |
685 | + for (gdouble y = ymin * lyw; y <= ybound; y += lyw, xlinenum++) { |
686 | + // Compute points in preimage coordinates |
687 | + gdouble const pc_x0 = fabs(y) / se_tan; |
688 | + gdouble const pc_x1 = lxmax; |
689 | + if (pc_x1 <= pc_x0) continue; |
690 | + // Compute points in grid coordinates (with rotation applied) |
691 | + gdouble const ys = y * section_sin; |
692 | + gdouble const yc = y * section_cos; |
693 | + gdouble const gc_x0 = ( (pc_x0 * section_cos) - ys ) + ow[Geom::X]; |
694 | + gdouble const gc_x1 = ( (pc_x1 * section_cos) - ys ) + ow[Geom::X]; |
695 | + gdouble const gc_y0 = ( (pc_x0 * section_sin) + yc ) + ow[Geom::Y]; |
696 | + gdouble const gc_y1 = ( (pc_x1 * section_sin) + yc ) + ow[Geom::Y]; |
697 | + // Draw segment |
698 | + guint32 const _color = ( (!scaled && (xlinenum % empspacing) != 0) ? color : _empcolor); |
699 | + sp_cngongrid_drawline (buf, gc_x0, gc_y0, gc_x1, gc_y1, _color); |
700 | + } |
701 | + |
702 | + // Render concentric lines |
703 | + xmin = std::max(1.0, ceil(xmin)); |
704 | + gint ylinenum = xmin; |
705 | + for (gdouble x = xmin * lxw; x < xbound; x += lxw, ylinenum++) { |
706 | + // Compute points in preimage coordinates |
707 | + gdouble const pc_y = x * se_tan; |
708 | + // Compute points in grid coordinates (with rotation applied) |
709 | + gdouble const xs = x * section_sin; |
710 | + gdouble const xc = x * section_cos; |
711 | + gdouble const ys = pc_y * section_sin; |
712 | + gdouble const yc = pc_y * section_cos; |
713 | + gdouble const gc_x0 = xc + ys + ow[Geom::X]; |
714 | + gdouble const gc_x1 = xc - ys + ow[Geom::X]; |
715 | + gdouble const gc_y0 = xs - yc + ow[Geom::Y]; |
716 | + gdouble const gc_y1 = xs + yc + ow[Geom::Y]; |
717 | + // Draw segment |
718 | + guint32 const _color = ( (!scaled && (ylinenum % empspacing) != 0) ? color : _empcolor); |
719 | + sp_cngongrid_drawline (buf, gc_x0, gc_y0, gc_x1, gc_y1, _color); |
720 | + } |
721 | +} |
722 | + |
723 | +CanvasNGonGridSnapper::CanvasNGonGridSnapper(CanvasNGonGrid *grid, SnapManager *sm, Geom::Coord const d) : LineSnapper(sm, d) |
724 | +{ |
725 | + this->grid = grid; |
726 | +} |
727 | + |
728 | +/** |
729 | + * \return Snap tolerance (desktop coordinates); depends on current zoom so that it's always the same in screen pixels |
730 | + */ |
731 | +Geom::Coord CanvasNGonGridSnapper::getSnapperTolerance() const |
732 | +{ |
733 | + SPDesktop const *dt = _snapmanager->getDesktop(); |
734 | + double const zoom = dt ? dt->current_zoom() : 1; |
735 | + return _snapmanager->snapprefs.getGridTolerance() / zoom; |
736 | +} |
737 | + |
738 | +bool CanvasNGonGridSnapper::getSnapperAlwaysSnap() const |
739 | +{ |
740 | + return _snapmanager->snapprefs.getGridTolerance() == 10000; //TODO: Replace this threshold of 10000 by a constant; see also tolerance-slider.cpp |
741 | +} |
742 | + |
743 | +LineSnapper::LineList |
744 | +CanvasNGonGridSnapper::_getSnapLines(Geom::Point const &p) const |
745 | +{ |
746 | + LineList s; |
747 | + |
748 | + if ( grid == NULL ) { |
749 | + return s; |
750 | + } |
751 | + |
752 | + double spacing_h; |
753 | + double spacing_v; |
754 | + |
755 | + if (getSnapVisibleOnly()) { |
756 | + // Only snapping to visible grid lines |
757 | + spacing_h = grid->lxw; // horizontal |
758 | + spacing_v = grid->lyw; // vertical |
759 | + // convert screen pixels to px |
760 | + // FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary |
761 | + SPDesktop const *dt = _snapmanager->getDesktop(); |
762 | + if (dt) { |
763 | + spacing_h /= dt->current_zoom(); |
764 | + spacing_v /= dt->current_zoom(); |
765 | + } |
766 | + } else { |
767 | + // Snapping to any grid line, whether it's visible or not |
768 | + spacing_h = grid->lengthx; |
769 | + spacing_v = grid->lengthy; |
770 | + } |
771 | + |
772 | + // In a polygonal grid, any point will be surrounded by 6 grid lines: |
773 | + // - 4 lines of a section grid |
774 | + // - 2 lines of the section edges |
775 | + // Of these, we use the closer section edge, and the closer each of the grid X and Y lines |
776 | + |
777 | + // Calculate what section the point is in |
778 | + Geom::Point gc_point = p - grid->origin; |
779 | + double point_angle_rad; |
780 | + bool const x_is_zero = Geom::are_near(gc_point[Geom::X], 0.); |
781 | + bool const y_is_zero = Geom::are_near(gc_point[Geom::Y], 0.); |
782 | + if (Geom::are_near(p, grid->origin)) |
783 | + point_angle_rad = 0; |
784 | + else |
785 | + point_angle_rad = Geom::atan2(gc_point); |
786 | + double const section_ratio = (point_angle_rad - grid->angle_rad - grid->se_angle_rad) / (2.0 * M_PI); |
787 | + int const section = floor( grid->sections * section_ratio ) + 1; |
788 | + |
789 | + // Compute spacing-unit vectors for section |
790 | + double const section_angle_rad = (2.0 * section * grid->se_angle_rad) + grid->angle_rad; |
791 | + double const section_sin = sin(section_angle_rad); |
792 | + double const section_cos = cos(section_angle_rad); |
793 | + Geom::Point const gc_nx(-section_sin, section_cos); |
794 | + Geom::Point const gc_ny( section_cos, section_sin); |
795 | + Geom::Point const gc_sx = gc_ny * spacing_h; |
796 | + Geom::Point const gc_sy = gc_nx * spacing_v; |
797 | + |
798 | + // Get point in section pre-image space |
799 | + double const pc_x = ( (gc_point[Geom::Y] * section_sin) + (gc_point[Geom::X] * section_cos) ) / spacing_h; |
800 | + double const pc_y = ( (gc_point[Geom::Y] * section_cos) - (gc_point[Geom::X] * section_sin) ) / spacing_v; |
801 | + |
802 | + // Add the nearer section edge line |
803 | + double const section_edge_angle_rad = section_angle_rad + ( (pc_y > 0.0 ? 1.0 : -1.0) * grid->se_angle_rad); |
804 | + Geom::Point const section_edge_norm(-sin(section_edge_angle_rad), cos(section_edge_angle_rad)); |
805 | + s.push_back( std::make_pair(section_edge_norm, grid->origin) ); |
806 | + |
807 | + // Add the two nearer lines of the grid square |
808 | + Geom::Point const gc_corner = (gc_sx * round(pc_x)) + (gc_sy * round(pc_y)) + grid->origin; |
809 | + s.push_back( std::make_pair(gc_nx, gc_corner) ); |
810 | + s.push_back( std::make_pair(gc_ny, gc_corner) ); |
811 | + |
812 | + return s; |
813 | +} |
814 | + |
815 | +void CanvasNGonGridSnapper::_addSnappedLine(IntermSnapResults &isr, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const |
816 | +{ |
817 | + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, source_num, Inkscape::SNAPTARGET_GRID, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); |
818 | + isr.grid_lines.push_back(dummy); |
819 | +} |
820 | + |
821 | +void CanvasNGonGridSnapper::_addSnappedPoint(IntermSnapResults &isr, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const |
822 | +{ |
823 | + SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); |
824 | + isr.points.push_back(dummy); |
825 | +} |
826 | + |
827 | +void CanvasNGonGridSnapper::_addSnappedLinePerpendicularly(IntermSnapResults &isr, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const |
828 | +{ |
829 | + SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID_PERPENDICULAR, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); |
830 | + isr.points.push_back(dummy); |
831 | +} |
832 | + |
833 | +bool CanvasNGonGridSnapper::ThisSnapperMightSnap() const |
834 | +{ |
835 | + return _snap_enabled && _snapmanager->snapprefs.isTargetSnappable(Inkscape::SNAPTARGET_GRID); |
836 | +} |
837 | + |
838 | + |
839 | +}; // namespace Inkscape |
840 | + |
841 | + |
842 | +/* |
843 | + Local Variables: |
844 | + mode:c++ |
845 | + c-file-style:"stroustrup" |
846 | + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
847 | + indent-tabs-mode:nil |
848 | + fill-column:99 |
849 | + End: |
850 | +*/ |
851 | +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |
852 | |
853 | === added file 'src/display/canvas-ngongrid.h' |
854 | --- src/display/canvas-ngongrid.h 1970-01-01 00:00:00 +0000 |
855 | +++ src/display/canvas-ngongrid.h 2016-04-29 07:04:20 +0000 |
856 | @@ -0,0 +1,94 @@ |
857 | +#ifndef CANVAS_NGONGRID_H |
858 | +#define CANVAS_NGONGRID_H |
859 | + |
860 | +/* |
861 | + * Authors: |
862 | + * Matthew Woehlke <mw_triad@users.sourceforge.net> |
863 | + * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl> |
864 | + * |
865 | + * Copyright (C) 2006-2012 Authors |
866 | + * Released under GNU GPL, read the file 'COPYING' for more information |
867 | + */ |
868 | + |
869 | +#include "line-snapper.h" |
870 | +#include "canvas-grid.h" |
871 | + |
872 | +class SPCanvasBuf; |
873 | +class SPDesktop; |
874 | +struct SPNamedView; |
875 | + |
876 | +namespace Inkscape { |
877 | +namespace XML { |
878 | + class Node; |
879 | +}; |
880 | + |
881 | +class CanvasNGonGrid : public CanvasGrid { |
882 | +public: |
883 | + CanvasNGonGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc); |
884 | + virtual ~CanvasNGonGrid(); |
885 | + |
886 | + void Update (Geom::Affine const &affine, unsigned int flags); |
887 | + void Render (SPCanvasBuf *buf); |
888 | + |
889 | + void readRepr(); |
890 | + void onReprAttrChanged (Inkscape::XML::Node * repr, const gchar *key, const gchar *oldval, const gchar *newval, bool is_interactive); |
891 | + |
892 | + int sections; /**< Number of grid sections */ |
893 | + double lengthx; /**< Step size along concentric polygons */ |
894 | + double lengthy; /**< Step size along semi-radius lines */ |
895 | + double angle_deg; /**< Angle of rotation (degrees) */ |
896 | + double angle_rad; /**< Angle of rotation (radians) */ |
897 | + double se_angle_deg; /**< Half of section arc (degrees) */ |
898 | + double se_angle_rad; /**< Half of section arc (radians) */ |
899 | + double se_tan; /**< tan(se_angle) */ |
900 | + |
901 | + bool scaled; /**< Whether the grid is in scaled mode */ |
902 | + |
903 | +protected: |
904 | + friend class CanvasNGonGridSnapper; |
905 | + |
906 | + Geom::Point ow; /**< Transformed origin by the affine for the zoom */ |
907 | + double lxw; /**< Transformed length x by the affine for the zoom */ |
908 | + double lyw; /**< Transformed length y by the affine for the zoom */ |
909 | + |
910 | + Geom::Point sw; /**< the scaling factors of the affine transform */ |
911 | + |
912 | + virtual Gtk::Widget * newSpecificWidget(); |
913 | + |
914 | +private: |
915 | + CanvasNGonGrid(const CanvasNGonGrid&); |
916 | + CanvasNGonGrid& operator=(const CanvasNGonGrid&); |
917 | + |
918 | + void updateWidgets(); |
919 | + |
920 | + void renderSection (SPCanvasBuf *buf, double section_angle_deg, guint32 _empcolor); |
921 | +}; |
922 | + |
923 | + |
924 | + |
925 | +class CanvasNGonGridSnapper : public LineSnapper |
926 | +{ |
927 | +public: |
928 | + CanvasNGonGridSnapper(CanvasNGonGrid *grid, SnapManager *sm, Geom::Coord const d); |
929 | + bool ThisSnapperMightSnap() const; |
930 | + |
931 | + Geom::Coord getSnapperTolerance() const; //returns the tolerance of the snapper in screen pixels (i.e. independent of zoom) |
932 | + bool getSnapperAlwaysSnap() const; //if true, then the snapper will always snap, regardless of its tolerance |
933 | + |
934 | +private: |
935 | + LineList _getSnapLines(Geom::Point const &p) const; |
936 | + void _addSnappedLine(IntermSnapResults &isr, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; |
937 | + void _addSnappedPoint(IntermSnapResults &isr, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; |
938 | + void _addSnappedLinePerpendicularly(IntermSnapResults &isr, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; |
939 | + |
940 | + CanvasNGonGrid *grid; |
941 | +}; |
942 | + |
943 | + |
944 | +}; //namespace Inkscape |
945 | + |
946 | + |
947 | + |
948 | +#endif |
949 | + |
950 | + |
951 | |
952 | === modified file 'src/ui/dialog/document-properties.cpp' |
953 | --- src/ui/dialog/document-properties.cpp 2016-02-21 21:44:25 +0000 |
954 | +++ src/ui/dialog/document-properties.cpp 2016-04-29 07:04:20 +0000 |
955 | @@ -1386,6 +1386,8 @@ |
956 | case GRID_AXONOMETRIC: |
957 | icon = "grid-axonometric"; |
958 | break; |
959 | + case GRID_POLYGONAL: |
960 | + icon = "grid-polygonal"; |
961 | default: |
962 | break; |
963 | } |
964 | |
965 | === modified file 'src/ui/dialog/inkscape-preferences.cpp' |
966 | --- src/ui/dialog/inkscape-preferences.cpp 2016-04-12 10:28:18 +0000 |
967 | +++ src/ui/dialog/inkscape-preferences.cpp 2016-04-29 07:04:20 +0000 |
968 | @@ -514,7 +514,7 @@ |
969 | this->AddPage(_page_dropper, _("Dropper"), iter_tools, PREFS_PAGE_TOOLS_DROPPER); |
970 | this->AddSelcueCheckbox(_page_dropper, "/tools/dropper", true); |
971 | this->AddGradientCheckbox(_page_dropper, "/tools/dropper", true); |
972 | - |
973 | + |
974 | //Connector |
975 | this->AddPage(_page_connector, _("Connector"), iter_tools, PREFS_PAGE_TOOLS_CONNECTOR); |
976 | this->AddSelcueCheckbox(_page_connector, "/tools/connector", true); |
977 | @@ -689,7 +689,7 @@ |
978 | |
979 | _win_native.init ( _("Native open/save dialogs"), "/options/desktopintegration/value", 1, true, 0); |
980 | _win_gtk.init ( _("GTK open/save dialogs"), "/options/desktopintegration/value", 0, false, &_win_native); |
981 | - |
982 | + |
983 | _win_hide_task.init ( _("Dialogs are hidden in taskbar"), "/options/dialogsskiptaskbar/value", true); |
984 | _win_save_viewport.init ( _("Save and restore documents viewport"), "/options/savedocviewport/value", true); |
985 | _win_zoom_resize.init ( _("Zoom when window is resized"), "/options/stickyzoom/value", false); |
986 | @@ -782,6 +782,7 @@ |
987 | _page_grids.add_line( true, "", _grids_notebook, "", "", false); |
988 | _grids_notebook.append_page(_grids_xy, CanvasGrid::getName( GRID_RECTANGULAR )); |
989 | _grids_notebook.append_page(_grids_axonom, CanvasGrid::getName( GRID_AXONOMETRIC )); |
990 | + _grids_notebook.append_page(_grids_ngon, CanvasGrid::getName( GRID_POLYGONAL )); |
991 | _grids_xy_units.init("/options/grids/xy/units"); |
992 | _grids_xy.add_line( false, _("Grid units:"), _grids_xy_units, "", "", false); |
993 | _grids_xy_origin_x.init("/options/grids/xy/origin_x", -10000.0, 10000.0, 0.1, 1.0, 0.0, false, false); |
994 | @@ -829,6 +830,33 @@ |
995 | _grids_axonom_empspacing.init("/options/grids/axonom/empspacing", 1.0, 1000.0, 1.0, 5.0, 5.0, true, false); |
996 | _grids_axonom.add_line( false, _("Major grid line every:"), _grids_axonom_empspacing, "", "", false); |
997 | |
998 | + // CanvasNGonGrid properties: |
999 | + _grids_ngon_units.init("/options/grids/ngon/units"); |
1000 | + _grids_ngon.add_line( false, _("Grid units:"), _grids_ngon_units, "", "", false); |
1001 | + _grids_ngon_origin_x.init("/options/grids/ngon/origin_x", -10000.0, 10000.0, 0.1, 1.0, 0.0, false, false); |
1002 | + _grids_ngon_origin_y.init("/options/grids/ngon/origin_y", -10000.0, 10000.0, 0.1, 1.0, 0.0, false, false); |
1003 | + _grids_ngon_origin_x.set_digits(5); |
1004 | + _grids_ngon_origin_y.set_digits(5); |
1005 | + _grids_ngon.add_line( false, _("Origin X:"), _grids_ngon_origin_x, "", _("X coordinate of grid origin"), false); |
1006 | + _grids_ngon.add_line( false, _("Origin Y:"), _grids_ngon_origin_y, "", _("Y coordinate of grid origin"), false); |
1007 | + _grids_ngon_sect_n.init("/options/grids/ngon/sect_n", 3.0, 360.0, 1.0, 3.0, 8.0, true, false); |
1008 | + _grids_ngon.add_line( false, _("Number of sections:"), _grids_ngon_empspacing, "", "", false); |
1009 | + _grids_ngon_spacing_x.init("/options/grids/ngon/spacing_x", 0.0, 10000.0, 0.1, 1.0, 1.0, false, false); |
1010 | + _grids_ngon_spacing_y.init("/options/grids/ngon/spacing_y", 0.0, 10000.0, 0.1, 1.0, 1.0, false, false); |
1011 | + _grids_ngon_spacing_x.set_digits(5); |
1012 | + _grids_ngon_spacing_y.set_digits(5); |
1013 | + _grids_ngon.add_line( false, _("Spacing X:"), _grids_ngon_spacing_x, "", _("Distance between concentric grid polygons"), false); |
1014 | + _grids_ngon.add_line( false, _("Spacing Y:"), _grids_ngon_spacing_y, "", _("Distance between semi-radial grid lines"), false); |
1015 | + _grids_ngon_rotation.init("/options/grids/ngon/rotation", -360.0, 360.0, 1.0, 0.0, 0.0, false, false); |
1016 | + _grids_ngon_rotation.set_digits(5); |
1017 | + _grids_ngon.add_line( false, _("Rotation:"), _grids_ngon_rotation, "", _("Angle of axis rotation"), false); |
1018 | + _grids_ngon_color.init(_("Minor grid line color:"), "/options/grids/ngon/color", 0x0000ff20); |
1019 | + _grids_ngon.add_line( false, _("Minor grid line color:"), _grids_ngon_color, "", _("Color used for normal grid lines"), false); |
1020 | + _grids_ngon_empcolor.init(_("Major grid line color:"), "/options/grids/ngon/empcolor", 0x0000ff40); |
1021 | + _grids_ngon.add_line( false, _("Major grid line color:"), _grids_ngon_empcolor, "", _("Color used for major (highlighted) grid lines"), false); |
1022 | + _grids_ngon_empspacing.init("/options/grids/ngon/empspacing", 1.0, 1000.0, 1.0, 5.0, 5.0, true, false); |
1023 | + _grids_ngon.add_line( false, _("Major grid line every:"), _grids_ngon_empspacing, "", "", false); |
1024 | + |
1025 | this->AddPage(_page_grids, _("Grids"), iter_ui, PREFS_PAGE_UI_GRIDS); |
1026 | |
1027 | initKeyboardShortcuts(iter_ui); |
1028 | @@ -1377,28 +1405,28 @@ |
1029 | _mask_mask_remove.init ( _("Remove clippath/mask object after applying"), "/options/maskobject/remove", true); |
1030 | _page_mask.add_line(false, "", _mask_mask_remove, "", |
1031 | _("After applying, remove the object used as the clipping path or mask from the drawing")); |
1032 | - |
1033 | + |
1034 | _page_mask.add_group_header( _("Before applying")); |
1035 | - |
1036 | + |
1037 | _mask_grouping_none.init( _("Do not group clipped/masked objects"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_NONE, true, 0); |
1038 | _mask_grouping_separate.init( _("Put every clipped/masked object in its own group"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_SEPARATE, false, &_mask_grouping_none); |
1039 | _mask_grouping_all.init( _("Put all clipped/masked objects into one group"), "/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_ALL, false, &_mask_grouping_none); |
1040 | - |
1041 | + |
1042 | _page_mask.add_line(true, "", _mask_grouping_none, "", |
1043 | _("Apply clippath/mask to every object")); |
1044 | - |
1045 | + |
1046 | _page_mask.add_line(true, "", _mask_grouping_separate, "", |
1047 | _("Apply clippath/mask to groups containing single object")); |
1048 | - |
1049 | + |
1050 | _page_mask.add_line(true, "", _mask_grouping_all, "", |
1051 | _("Apply clippath/mask to group containing all objects")); |
1052 | - |
1053 | + |
1054 | _page_mask.add_group_header( _("After releasing")); |
1055 | - |
1056 | + |
1057 | _mask_ungrouping.init ( _("Ungroup automatically created groups"), "/options/maskobject/ungrouping", true); |
1058 | _page_mask.add_line(true, "", _mask_ungrouping, "", |
1059 | _("Ungroup groups created when setting clip/mask")); |
1060 | - |
1061 | + |
1062 | this->AddPage(_page_mask, _("Clippaths and masks"), iter_behavior, PREFS_PAGE_BEHAVIOR_MASKS); |
1063 | |
1064 | |
1065 | @@ -1896,15 +1924,20 @@ |
1066 | |
1067 | /* the returned pointer should _not_ need to be deleted */ |
1068 | AspellDictInfoList *dlist = get_aspell_dict_info_list(config); |
1069 | - |
1070 | + |
1071 | /* config is no longer needed */ |
1072 | delete_aspell_config(config); |
1073 | - |
1074 | + |
1075 | AspellDictInfoEnumeration *dels = aspell_dict_info_list_elements(dlist); |
1076 | +<<<<<<< TREE |
1077 | |
1078 | languages.push_back(Glib::ustring(C_("Spellchecker language", "None"))); |
1079 | +======= |
1080 | + |
1081 | + languages.push_back(Glib::ustring(_("None"))); |
1082 | +>>>>>>> MERGE-SOURCE |
1083 | langValues.push_back(Glib::ustring("")); |
1084 | - |
1085 | + |
1086 | const AspellDictInfo *entry; |
1087 | int en_index = 0; |
1088 | int i = 0; |
1089 | |
1090 | === modified file 'src/ui/dialog/inkscape-preferences.h' |
1091 | --- src/ui/dialog/inkscape-preferences.h 2016-03-02 19:44:36 +0000 |
1092 | +++ src/ui/dialog/inkscape-preferences.h 2016-04-29 07:04:20 +0000 |
1093 | @@ -411,6 +411,7 @@ |
1094 | UI::Widget::PrefRadioButton _grids_emphasize_on_zoom; |
1095 | UI::Widget::DialogPage _grids_xy; |
1096 | UI::Widget::DialogPage _grids_axonom; |
1097 | + UI::Widget::DialogPage _grids_ngon; |
1098 | // CanvasXYGrid properties: |
1099 | UI::Widget::PrefUnit _grids_xy_units; |
1100 | UI::Widget::PrefSpinButton _grids_xy_origin_x; |
1101 | @@ -431,6 +432,17 @@ |
1102 | UI::Widget::PrefColorPicker _grids_axonom_color; |
1103 | UI::Widget::PrefColorPicker _grids_axonom_empcolor; |
1104 | UI::Widget::PrefSpinButton _grids_axonom_empspacing; |
1105 | + // CanvasNGonGrid properties: |
1106 | + UI::Widget::PrefUnit _grids_ngon_units; |
1107 | + UI::Widget::PrefSpinButton _grids_ngon_origin_x; |
1108 | + UI::Widget::PrefSpinButton _grids_ngon_origin_y; |
1109 | + UI::Widget::PrefSpinButton _grids_ngon_sect_n; |
1110 | + UI::Widget::PrefSpinButton _grids_ngon_spacing_x; |
1111 | + UI::Widget::PrefSpinButton _grids_ngon_spacing_y; |
1112 | + UI::Widget::PrefSpinButton _grids_ngon_rotation; |
1113 | + UI::Widget::PrefColorPicker _grids_ngon_color; |
1114 | + UI::Widget::PrefColorPicker _grids_ngon_empcolor; |
1115 | + UI::Widget::PrefSpinButton _grids_ngon_empspacing; |
1116 | |
1117 | // SVG Output page: |
1118 | UI::Widget::PrefCheckButton _svgoutput_usenamedcolors; |
@Matthew - I know you submitted your branch a long time ago, and I'm sorry we didn't find time to review it sooner. But I'm sure it's an interesting feature and it would be great if we could port it to the current development code. preferences. cpp, or give ownership of the branch to the "Inkscape Developers" group so that we can work on it directly?
Would you be willing to fix the conflicts in canvas-grip.cpp and inkscape-
Thanks!