Commit c51d71c
optimizations of justaposed glyphs and object boundries
Changed files (7)
modifiedlibbirdfont/DrawingTools.valamodifiedlibbirdfont/EditPoint.valamodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/OpenFontFormat/load_font.cmodifiedlibbirdfont/Path.valamodifiedlibbirdfont/PenTool.valamodifiedlibbirdfont/Preferences.vala
Diff
@@ -123,6 +123,7 @@ public class DrawingTools : ToolCollection { } p.set_tie_handle (tie);+ p.get_path ().update_region_boundries_for_point (p); } else { foreach (EditPoint ep in PenTool.selected_points) { tie = !ep.tie_handles;@@ -133,9 +134,11 @@ public class DrawingTools : ToolCollection { } ep.set_tie_handle (tie);+ ep.get_path ().update_region_boundries_for_point (ep); } } + MainWindow.get_current_glyph ().update_view (); }); edit_point_modifiers.add_tool (tie_handles);@@ -157,6 +160,7 @@ public class DrawingTools : ToolCollection { } } + ep.get_path ().update_region_boundries_for_point (ep); MainWindow.get_current_glyph ().update_view (); } });@@ -49,6 +49,8 @@ public class EditPoint { public bool tie_handles = false; public bool reflective_handles = false; + Path? path = null;+ public EditPoint (double nx = 0, double ny = 0, PointType nt = PointType.NONE) { x = nx; y = ny;@@ -71,6 +73,18 @@ public class EditPoint { } } + public void set_path (Path p) {+ path = p;+ }++ public Path get_path () {+ if (unlikely (path == null)) {+ warning ("path is null");+ return new Path ();+ } + return (!) path;+ }+ public bool equals (EditPoint e) { return e.x == x && e.y == y @@ -1361,7 +1361,7 @@ public class Glyph : FontDisplay { public void draw_path (Context cr) { double left, baseline;- + baseline = get_line ("baseline").pos; left = get_line ("left").pos; @@ -1380,7 +1380,7 @@ public class Glyph : FontDisplay { cr.restore (); } }- + if (is_open ()) { foreach (unowned Path p in path_list) { p.draw_outline (cr, allocation, view_zoom);@@ -1443,6 +1443,12 @@ public class Glyph : FontDisplay { if (background_image != null && background_image_visible) { ((!)background_image).draw (cr, allocation, view_offset_x, view_offset_y, view_zoom); }++ if (unlikely (Preferences.draw_boundries)) {+ foreach (unowned Path p in path_list) {+ p.draw_boundries (cr, allocation, view_zoom);+ }+ } draw_background_glyph (allocation, cr); juxtapose (allocation, cr);@@ -1734,6 +1740,10 @@ public class Glyph : FontDisplay { return false; } + static bool in_range (double offset_x, double coordinate_x1, double coordinate_x2) {+ return coordinate_x1 <= offset_x <= coordinate_x2;+ }+ public void juxtapose (WidgetAllocation allocation, Context cr) { string glyph_sequence = Preferences.get ("glyph_sequence"); unichar c;@@ -1746,9 +1756,17 @@ public class Glyph : FontDisplay { double x, kern; double left, baseline; string last_name;- + + double box_x1, box_x2, box_y1, box_y2;+ double marker_x, marker_y;+ x = 0; + box_x1 = path_coordinate_x (0);+ box_y1 = path_coordinate_y (0);+ box_x2 = path_coordinate_x (allocation.width);+ box_y2 = path_coordinate_y (allocation.height);+ current.append_unichar (glyph.unichar_code); pos = glyph_sequence.index_of (current.str); @@ -1767,20 +1785,27 @@ public class Glyph : FontDisplay { } else { kern = 0; }+ + if (!juxtaposed.is_empty ()+ && (in_range (left + x + kern, box_x1, box_x2) // the letter is visible+ || in_range (left + x + kern + juxtaposed.get_width (), box_x1, box_x2))) { - if (!juxtaposed.is_empty ()) {+ marker_x = Glyph.xc () + left + x + kern - glyph.view_offset_x;+ marker_y = Glyph.yc () + baseline - glyph.view_offset_y;+ cr.save (); cr.scale (glyph.view_zoom, glyph.view_zoom);- cr.translate (-glyph.view_offset_x, -glyph.view_offset_y); cr.set_source_rgba (0, 0, 0, 1);- Svg.draw_svg_path (cr, juxtaposed.get_svg_data (), Glyph.xc () + left + x + kern, Glyph.yc () + baseline);++ Svg.draw_svg_path (cr, juxtaposed.get_svg_data (), marker_x, marker_y); cr.restore (); } - x += juxtaposed.get_width () + KerningClasses.get_instance ().get_kerning (glyph.name, name) + kern;+ x += juxtaposed.get_width () + kern;+ last_name = name; }- + x = 0; last_name = glyph.name; for (int i = pos - 1; i >= 0; i--) {@@ -1797,17 +1822,21 @@ public class Glyph : FontDisplay { x -= juxtaposed.get_width (); x -= kern; - if (!juxtaposed.is_empty ()) {+ marker_x = Glyph.xc () + left + x;+ marker_y = Glyph.yc () + baseline;+ if (!juxtaposed.is_empty () + &&(in_range (left + x, box_x1, box_x2)+ || in_range (left + x + juxtaposed.get_width (), box_x1, box_x2))) { cr.save (); cr.scale (glyph.view_zoom, glyph.view_zoom); cr.translate (-glyph.view_offset_x, -glyph.view_offset_y); cr.set_source_rgba (0, 0, 0, 1);- Svg.draw_svg_path (cr, juxtaposed.get_svg_data (), Glyph.xc () + left + x, Glyph.yc () + baseline);+ Svg.draw_svg_path (cr, juxtaposed.get_svg_data (), marker_x, marker_y); cr.restore (); } last_name = name;- } + } } void draw_background_glyph (WidgetAllocation allocation, Context cr) {@@ -748,6 +748,7 @@ GString* get_bf_font (FT_Face face, char* file, int* err) { g_string_append (bf, "</version>\n"); } + // FIXME: for some fonts will this return entry 0 (copyright) if (FT_Get_Sfnt_Name (face, 10, &name_table_data) == 0) { // description g_string_append (bf, "<description>"); append_description (bf, &name_table_data);@@ -129,6 +129,22 @@ public class Path { return points.length () == 0; } + public void draw_boundries (Context cr, WidgetAllocation allocation, double view_zoom) {+ double x = Glyph.reverse_path_coordinate_x (xmin); + double y = Glyph.reverse_path_coordinate_y (ymin);+ double x2 = Glyph.reverse_path_coordinate_x (xmax);+ double y2 = Glyph.reverse_path_coordinate_y (ymax);+ + cr.save ();+ + cr.set_source_rgba (0, 0, 0.3, 1);+ cr.set_line_width (2);+ cr.rectangle (x, y, x2 - x, y2 - y);+ cr.stroke ();+ + cr.restore ();+ }+ public void draw_outline (Context cr, WidgetAllocation allocation, double view_zoom) { unowned List<EditPoint> ep = points; @@ -871,6 +887,8 @@ public class Path { second_last_point = last_point; last_point = p; + p.set_path (this);+ return np; } @@ -915,141 +933,66 @@ public class Path { update_region_boundries (); } - public void update_region_boundries () {- double txmax = -10000;- double txmin = 10000;- double tymax = -10000;- double tymin = 10000;- - EditPoint top = new EditPoint ();- EditPoint bottom = new EditPoint ();- EditPoint left = new EditPoint ();- EditPoint right = new EditPoint ();+ public void update_region_boundries_for_point (EditPoint p) {+ EditPointHandle left_handle;+ EditPointHandle right_handle; - if (points.length () == 0) {- xmax = 0;- xmin = 0;- ymax = 0;- ymin = 0; - }-- // on curve points- foreach (EditPoint p in points) {- if (p.x > txmax) {- txmax = p.x;- right = p;- }- - if (p.x < txmin) {- txmin = p.x;- left = p;- }-- if (p.y > tymax) {- tymax = p.y;- top = p;- }+ left_handle = p.get_left_handle ();+ right_handle = p.get_right_handle (); - if (p.y < tymin) {- tymin = p.y;- bottom = p;- }+ if (p.x > xmax) {+ xmax = p.x; }-- xmax = -10000;- xmin = 10000;- ymax = -10000;- ymin = 10000;-- bool new_val = false; - // TODO: optimize (iterate over only x or y)- - if (top.prev != null) {- all_of (top.get_prev ().data, top, (cx, cy) => {- if (cy > tymax) {- tymax = cy;- }- return true;- });+ if (p.x < xmin) {+ xmin = p.x; } - if (top.next != null) {- all_of (top, top.get_next ().data, (cx, cy) => {- if (cy > tymax) {- tymax = cy;- }- return true;- });+ if (p.y > ymax) {+ ymax = p.y; }- - if (bottom.prev != null) {- all_of (bottom.get_prev ().data, bottom, (cx, cy) => {- if (cy < tymin) {- tymin = cy;- }- return true;- });- }- - if (bottom.next != null) {- all_of (bottom, bottom.get_next ().data, (cx, cy) => {- if (cy < tymin) {- tymin = cy;- }- return true;- });++ if (p.y < ymin) {+ ymin = p.y; } - if (right.prev != null) {- all_of (right.get_prev ().data, right, (cx, cy) => {- if (cx > txmax) {- txmax = cx;- }- return true;- });+ update_region_boundries_for_handle (left_handle);+ update_region_boundries_for_handle (right_handle);+ }++ public void update_region_boundries_for_handle (EditPointHandle h) {+ if (h.x () > xmax) {+ xmax = h.x (); } - if (right.next != null) {- all_of (right, right.get_next ().data, (cx, cy) => {- if (cx > txmax) {- txmax = cx;- }- return true;- });+ if (h.x () < xmin) {+ xmin = h.x (); } - if (left.prev != null) {- all_of (left.get_prev ().data, left, (cx, cy) => {- if (cx < txmin) {- txmin = cx;- }- return true;- });+ if (h.y () > ymax) {+ ymax = h.y (); } - if (left.next != null) {- all_of (left, left.get_next ().data, (cx, cy) => {- if (cx < txmin) {- txmin = cx;- }- return true;- });+ if (h.y () < ymin) {+ ymin = h.y (); }- - xmax = txmax;- xmin = txmin;- ymax = tymax;- ymin = tymin;+ } + public void update_region_boundries () {+ xmax = -10000;+ xmin = 10000;+ ymax = -10000;+ ymin = 10000;+ if (points.length () == 0) { xmax = 0; xmin = 0; ymax = 0;- ymin = 0;- } else if (unlikely (!got_region_boundries ())) {- warning (@"No new region boundries.\nPoints.length: $(points.length ())");- print_boundries ();+ ymin = 0; + }++ foreach (EditPoint p in points) {+ update_region_boundries_for_point (p); } } @@ -274,6 +274,7 @@ public class PenTool : Tool { } selected_handle.parent.recalculate_linear_handles ();+ selected_handle.parent.get_path ().update_region_boundries_for_handle (selected_handle); // Fixa: redraw line only glyph.redraw_area (0, 0, glyph.allocation.width, glyph.allocation.height);@@ -302,8 +303,8 @@ public class PenTool : Tool { } else { glyph.move_selected_edit_point_delta (p, (x - last_point_x) * precision, (y - last_point_y) * precision); }- p.recalculate_linear_handles ();+ p.get_path ().update_region_boundries_for_point (p); } } @@ -18,6 +18,7 @@ using Gee; public class Preferences { static Gee.HashMap<string, string> data;+ public static bool draw_boundries = false; public Preferences () { data = new HashMap<string, string> ();