Commit a0eed47
Merge branch 'master' of gitorious.org:birdfont/birdfont
Changed files (8)
addedicons/create_line.pngaddedicons/symmetric.pngmodifiedlibbirdfont/EditPoint.valamodifiedlibbirdfont/EditPointHandle.valamodifiedlibbirdfont/Path.valamodifiedlibbirdfont/PenTool.valamodifiedlibbirdfont/Preview.valamodifiedlibbirdfont/Toolbox.vala
Diff
new file mode 100644Binary files /dev/null and b/icons/create_line.png differnew file mode 100644Binary files /dev/null and b/icons/symmetric.png differ@@ -46,6 +46,7 @@ public class EditPoint { public EditPointHandle left_handle; public bool tie_handles = false;+ public bool reflective_handles = false; public EditPoint (double nx = 0, double ny = 0, PointType nt = PointType.NONE) { x = nx;@@ -78,6 +79,11 @@ public class EditPoint { && get_left_handle ().y () == e.get_left_handle ().y (); } + /** Make handles symetrical. */+ public void set_reflective_handles (bool symmetrical) {+ reflective_handles = symmetrical;+ }+ /** Flip handles if next point on path is in the other direction. * Used to recalculate handles after new point is inserted on a path. */@@ -212,6 +218,12 @@ public class EditPoint { public void set_tie_handle (bool t) { tie_handles = t; }+ + public void process_symmetrical_handles () {+ process_tied_handle ();+ right_handle.process_symmetrical_handle ();+ left_handle.process_symmetrical_handle ();+ } /** This can only be performed if the path has been closed. */ public void process_tied_handle () @@ -335,16 +347,26 @@ public class EditPoint { public void set_position (double tx, double ty) { x = tx; y = ty;-+ if (unlikely (tx.is_nan () || ty.is_nan ())) { warning (@"Invalid point at ($tx,$ty)."); x = 0; y = 0; } - if (type == PointType.QUADRATIC) {- right_handle.process_connected_handle ();- left_handle.process_connected_handle ();+ // move connected quadratic handle+ if (left_handle.type == PointType.QUADRATIC || right_handle.type == PointType.QUADRATIC) {+ if (next != null) {+ ((!)next).data.set_tie_handle (false);+ ((!)next).data.set_reflective_handles (false);+ ((!)next).data.left_handle.move_to_coordinate_internal (right_handle.x (), right_handle.y ());+ }++ if (prev != null && !((!)prev).data.is_selected ()) {+ ((!)prev).data.set_tie_handle (false);+ ((!)prev).data.set_reflective_handles (false);+ ((!)prev).data.right_handle.move_to_coordinate (left_handle.x (), left_handle.y ());+ } } } @@ -116,13 +116,20 @@ public class EditPointHandle { public void move_to_coordinate (double x, double y) { move_to_coordinate_internal (x, y);+ if (parent.tie_handles) { tie_handle (); }+ + if (parent.reflective_handles) {+ tie_handle ();+ process_symmetrical_handle ();+ }+ process_connected_handle (); } - private void move_to_coordinate_internal (double x, double y) {+ public void move_to_coordinate_internal (double x, double y) { double a, b, c; a = parent.x - x;@@ -168,6 +175,18 @@ public class EditPointHandle { } } + public void process_symmetrical_handle () {+ if (is_left_handle ()) {+ parent.get_right_handle ().length = length;+ parent.get_right_handle ().process_connected_handle ();+ } else {+ parent.get_left_handle ().length = length;+ parent.get_left_handle ().process_connected_handle ();+ }+ + process_connected_handle ();+ }+ public void tie_handle () { if (is_left_handle ()) { parent.get_right_handle ().angle = angle - PI;@@ -811,6 +811,10 @@ public class Path { prev_index = points.position ((!) previous_point); np = points.nth (prev_index + 1);+ + if (unlikely (p.prev == null)) {+ warning ("Prev point is null");+ } } second_last_point = last_point;@@ -1565,7 +1569,7 @@ public class Path { } public void create_list () {- unowned List<EditPoint> prev = points.last ();;+ unowned List<EditPoint> prev = points.last (); unowned List<EditPoint> ep = points.first (); if (points.length () == 0) {@@ -78,14 +78,17 @@ public class PenTool : Tool { press_action.connect ((self, b, x, y) => { first_move_action = true; + last_point_x = x;+ last_point_y = y;++ press (b, x, y, false);+ if (GridTool.is_visible ()) { tie_pixels (ref x, ref y); } last_point_x = x; last_point_y = y;-- press (b, x, y, false); }); double_click_action.connect ((self, b, x, y) => {@@ -165,9 +168,11 @@ public class PenTool : Tool { double px = 0; double py = 0; - control_point_event (x, y);- curve_active_corner_event (x, y);- set_default_handle_positions ();+ // DELETE if (!move_selected_handle) {+ control_point_event (x, y);+ curve_active_corner_event (x, y);+ set_default_handle_positions (); // FIXME+ //} // show new point on path if (glyph.new_point_on_path != null) {@@ -187,7 +192,7 @@ public class PenTool : Tool { if (selected_handle.type == PointType.LINE_DOUBLE_CURVE) { selected_handle.set_point_type (PointType.DOUBLE_CURVE); }- + if (GridTool.is_visible ()) { coordinate_x = Glyph.path_coordinate_x (x); coordinate_y = Glyph.path_coordinate_y (y);@@ -329,6 +334,7 @@ public class PenTool : Tool { if (active_edit_point == null) { if (KeyBindings.modifier != SHIFT) { remove_all_selected_points ();+ return; } } @@ -347,10 +353,11 @@ public class PenTool : Tool { add_selected_point (selected_point); } } else {+ selected_point = (!)active_edit_point;+ if (!((!)active_edit_point).is_selected ()) { remove_all_selected_points (); ((!)active_edit_point).set_selected (true);- selected_point = (!)active_edit_point; add_selected_point (selected_point); }@@ -834,7 +841,7 @@ public class PenTool : Tool { double d_point = g.view_zoom * get_distance_to_closest_edit_point (event_x, event_y); double dl, dr;- + foreach (EditPoint selected_corner in selected_points) { dl = g.view_zoom * selected_corner.get_left_handle ().get_point ().get_distance (x, y); dr = g.view_zoom * selected_corner.get_right_handle ().get_point ().get_distance (x, y);@@ -1097,6 +1104,89 @@ public class PenTool : Tool { g.redraw_area (0, 0, g.allocation.width, g.allocation.height); } + public static void convert_point_to_line (EditPoint ep, bool both) {+ ep.set_tie_handle (false);+ ep.set_reflective_handles (false);+ + if (ep.type == PointType.CUBIC || ep.type == PointType.LINE_CUBIC) {+ ep.type = PointType.LINE_CUBIC;+ + if (both) {+ ep.get_left_handle ().type = PointType.LINE_CUBIC;+ ep.get_right_handle ().type = PointType.LINE_CUBIC;+ }+ + if (ep.next != null && ep.get_next ().data.is_selected ()) {+ ep.get_right_handle ().type = PointType.LINE_CUBIC;+ }++ if (ep.prev != null && ep.get_prev ().data.is_selected ()) {+ ep.get_left_handle ().type = PointType.LINE_CUBIC;+ }+ + }++ if (ep.type == PointType.DOUBLE_CURVE| ep.type == PointType.LINE_DOUBLE_CURVE) {+ ep.type = PointType.LINE_DOUBLE_CURVE;+ if (both) {+ ep.get_left_handle ().type = PointType.LINE_DOUBLE_CURVE;+ ep.get_right_handle ().type = PointType.LINE_DOUBLE_CURVE;+ }++ if (ep.next != null && ep.get_next ().data.is_selected ()) {+ ep.get_right_handle ().type = PointType.LINE_DOUBLE_CURVE;+ }++ if (ep.prev != null && ep.get_prev ().data.is_selected ()) {+ ep.get_left_handle ().type = PointType.LINE_DOUBLE_CURVE;+ }+ }++ if (ep.type == PointType.QUADRATIC || ep.type == PointType.LINE_QUADRATIC) {+ ep.type = PointType.LINE_QUADRATIC;+ + if (both) {+ ep.get_left_handle ().type = PointType.LINE_QUADRATIC;+ ep.get_right_handle ().type = PointType.LINE_QUADRATIC;+ + if (ep.next != null) {+ ep.get_next ().data.get_left_handle ().type = PointType.LINE_QUADRATIC; + }+ + if (ep.prev != null) {+ ep.get_prev ().data.get_right_handle ().type = PointType.LINE_QUADRATIC; + }+ }+ + if (ep.next != null && ep.get_next ().data.is_selected ()) {+ ep.get_right_handle ().type = PointType.LINE_QUADRATIC;+ ep.get_next ().data.get_left_handle ().type = PointType.LINE_QUADRATIC;+ }++ if (ep.prev != null && ep.get_prev ().data.is_selected ()) {+ ep.get_left_handle ().type = PointType.LINE_QUADRATIC;+ ep.get_prev ().data.get_right_handle ().type = PointType.LINE_QUADRATIC;+ } + + }+ + ep.recalculate_linear_handles ();+ }+ + public static void convert_segment_to_line () {+ if (selected_points.length () == 0) {+ return;+ }+ + if (selected_points.length () == 1) {+ convert_point_to_line (selected_points.first ().data, true);+ } else {+ foreach (EditPoint p in selected_points) {+ convert_point_to_line (p, false);+ }+ }+ }+ /** Draw a test glyph. */ public override bool test () { test_select_action ();@@ -30,7 +30,11 @@ public class Preview : FontDisplay { public override void selected_canvas () { } - public new File get_html_file () {+ public static string get_html_path () {+ return (!) get_file ().get_path ();+ }++ public static File get_file () { Font font = BirdFont.get_current_font (); string path = @"$(font.get_name ()).html"; File dir = font.get_folder ();@@ -40,7 +44,11 @@ public class Preview : FontDisplay { ExportTool.generate_html_document ((!)file.get_path (), font); } - return file; + return file;+ }++ public new File get_html_file () {+ return get_file (); } public override string get_uri () {@@ -54,5 +62,59 @@ public class Preview : FontDisplay { File file = dir.get_child (html); return "file:///" + (!) file.get_path (); }+ + public static string get_html_with_absolute_paths () { + // hack: force webkit to ignore cache in preview + StringBuilder sb = new StringBuilder ();+ DataInputStream dis ;+ string? line;+ + uint rid = Random.next_int ();+ Font font = BirdFont.get_current_font ();+ + File preview_directory;+ File f_ttf;+ File f_eot;+ File f_svg;+ + try {+ dis = new DataInputStream (get_file ().read ());+ + preview_directory = BirdFont.get_preview_directory ();+ + f_ttf = font.get_folder ().get_child (@"$(font.get_name ()).ttf");+ f_eot = font.get_folder ().get_child (@"$(font.get_name ()).eot");+ f_svg = font.get_folder ().get_child (@"$(font.get_name ()).svg");++ if (!f_ttf.query_exists ()) {+ warning ("TTF file does not exist.");+ }+ + if (!f_svg.query_exists ()) {+ warning ("SVG file does not exist.");+ }+ + File r_ttf = preview_directory.get_child (@"$(font.get_name ())$rid.ttf");+ File r_svg = preview_directory.get_child (@"$(font.get_name ())$rid.svg");+ + if (BirdFont.win32) {+ f_ttf.copy (r_ttf, FileCopyFlags.NONE);+ }+ + f_svg.copy (r_svg, FileCopyFlags.NONE);++ while ((line = dis.read_line (null)) != null) {+ line = ((!) line).replace (@"$(font.get_name ()).ttf", @"$(FontDisplay.path_to_uri ((!) f_ttf.get_path ()))?$rid");+ line = ((!) line).replace (@"$(font.get_name ()).eot", @"$(FontDisplay.path_to_uri ((!) f_eot.get_path ()))?$rid");+ line = ((!) line).replace (@"$(font.get_name ()).svg", @"$(FontDisplay.path_to_uri ((!) f_svg.get_path ()))?$rid");+ sb.append ((!) line);+ }+ } catch (Error e) {+ warning (e.message);+ warning ("Failed to load html into canvas.");+ }++ return sb.str;+ } } }@@ -59,6 +59,7 @@ public class Toolbox : GLib.Object { Expander path_tool_modifiers = new Expander (); Expander draw_tool_modifiers = new Expander ();+ Expander edit_point_modifiers = new Expander (); Expander characterset_tools = new Expander (); Expander test_tools = new Expander (); Expander guideline_tools = new Expander ();@@ -116,39 +117,50 @@ public class Toolbox : GLib.Object { if (tie) { ep.process_tied_handle ();+ ep.set_reflective_handles (false); }- + ep.set_tie_handle (tie);- MainWindow.get_current_glyph ().update_view (); } - // don't select the tie tool. give focus to the point type selection:- var idle = new IdleSource();- idle.set_callback (() => {- if (point_type == PointType.QUADRATIC) {- select_tool (quadratic_points);- }-- if (point_type == PointType.CUBIC) {- select_tool (cubic_points);- }-- if (point_type == PointType.DOUBLE_CURVE) {- select_tool (double_points);+ MainWindow.get_current_glyph ().update_view ();+ });+ edit_point_modifiers.add_tool (tie_handles);+ + // symmetrical handles+ Tool reflect_handle = new Tool ("symmetric", _("Symmetrical handles"), 'r');+ reflect_handle.select_action.connect ((self) => {+ bool symmetrical;+ EditPoint ep;+ if (PenTool.selected_points.length () > 0) {+ ep = PenTool.selected_points.first ().data;+ symmetrical = ep.reflective_handles;+ foreach (EditPoint p in PenTool.selected_points) {+ p.set_reflective_handles (!symmetrical);+ p.process_symmetrical_handles ();+ + if (symmetrical) {+ ep.set_tie_handle (false);+ } }- return false;- });- - idle.attach (null); + MainWindow.get_current_glyph ().update_view ();+ } });- draw_tool_modifiers.add_tool (tie_handles);- + edit_point_modifiers.add_tool (reflect_handle);++ Tool create_line = new Tool ("create_line", _("Convert segment to line."), 'r');+ create_line.select_action.connect ((self) => {+ PenTool.convert_segment_to_line ();+ MainWindow.get_current_glyph ().update_view ();+ });+ edit_point_modifiers.add_tool (create_line);+ // path tools Tool union_paths_tool = new MergeTool ("union_paths"); path_tool_modifiers.add_tool (union_paths_tool); - Tool reverse_path_tool = new Tool ("reverse_path", _("Create counter from outline"), 'r');+ Tool reverse_path_tool = new Tool ("reverse_path", _("Create counter from outline")); reverse_path_tool.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); @@ -549,6 +561,7 @@ public class Toolbox : GLib.Object { draw_tools.set_open (true); draw_tool_modifiers.set_open (true);+ edit_point_modifiers.set_open (true); path_tool_modifiers.set_open (true); view_tools.set_open (true); grid.set_open (true);@@ -560,6 +573,7 @@ public class Toolbox : GLib.Object { add_expander (draw_tools); add_expander (draw_tool_modifiers);+ add_expander (edit_point_modifiers); add_expander (path_tool_modifiers); add_expander (characterset_tools);@@ -579,6 +593,9 @@ public class Toolbox : GLib.Object { draw_tool_modifiers.set_persistent (true); draw_tool_modifiers.set_unique (true); + edit_point_modifiers.set_persistent (false);+ edit_point_modifiers.set_unique (false);+ path_tool_modifiers.set_persistent (false); path_tool_modifiers.set_unique (false);