Commit 898eb9d
cache background thumbnails
Changed files (10)
modifiedsrc/BackgroundSelection.valamodifiedsrc/BackgroundTool.valamodifiedsrc/CutBackgroundTool.valamodifiedsrc/Font.valamodifiedsrc/Glyph.valamodifiedsrc/GlyphBackgroundImage.valamodifiedsrc/Path.valamodifiedsrc/PenTool.valamodifiedsrc/SpinButton.valamodifiedsrc/Toolbox.vala
Diff
@@ -25,7 +25,6 @@ class BackgroundSelection : FontDisplay { int active_box = -1; ImageSurface add_icon;- CutBackgroundCanvas cut_background_canvas; List <string> background_images = new List <string> (); Allocation allocation; Glyph glyph;@@ -86,55 +85,41 @@ class BackgroundSelection : FontDisplay { cr.restore (); }+ + private ImageSurface create_thumbnail (string file) throws GLib.Error {+ Pixbuf pixbuf;+ + Font font = Supplement.get_current_font ();+ File folder = font.get_backgrounds_folder ();+ string fn = Checksum.compute_for_string (ChecksumType.SHA1, file);+ File original = File.new_for_path (file);+ File png_image = folder.get_child (@"thumbnail_$(fn).png"); + if (!png_image.query_exists ()) {+ pixbuf = new Pixbuf.from_file_at_scale ((!) original.get_path (), 100, 100, true);+ if (!pixbuf.save ((!) png_image.get_path (), "png")) {+ warning (@"can't save $((!) png_image.get_path ())");+ }+ }+ + return new ImageSurface.from_png ((!) png_image.get_path ());+ }+ private bool draw_thumbnail (string file, double x, double y, Context cr, int box_index) {- Pixbuf pixbuf; ImageSurface img;- uint8* data;- uint8* dest;- int pixels;- int pr, ir;- + try {- pixbuf = new Pixbuf.from_file_at_scale (file, 100, 100, true);- - if (is_null (pixbuf)) {- warning ("Failed to load pixbuf.");- return false;- }- - pixels = pixbuf.get_width () * pixbuf.get_height ();- - img = new ImageSurface (Format.ARGB32, pixbuf.get_width (), pixbuf.get_height ());+ img = create_thumbnail (file); - if (img.status () != Cairo.Status.SUCCESS) {- warning (@"Failed to load $file as gdk pixbuf. (height: $(pixbuf.get_height ()), width: $(pixbuf.get_width ()), stride: $(pixbuf.get_rowstride ()))");- return false;+ if (img.status () == Cairo.Status.SUCCESS) {+ cr.set_source_surface (img, x + 10, y + 10);+ cr.paint (); }- - data = pixbuf.get_pixels ();- dest = img.get_data ();- - assert (!is_null (data));- assert (!is_null (dest));-- pr = pixbuf.get_rowstride () / pixbuf.get_width ();- ir = img.get_stride () / img.get_width ();- - for (int i = 0; i < pixels; i++) {- dest[i * ir + 0] = data[i * pr + 2];- dest[i * ir + 1] = data[i * pr + 1];- dest[i * ir + 2] = data[i * pr + 0];- dest[i * ir + 3] = 255;- }- - img = new ImageSurface.for_data ((uchar[])dest, Format.ARGB32, pixbuf.get_width (), pixbuf.get_height (), img.get_stride ());-- cr.set_source_surface (img, x + 10, y + 10);- cr.paint (); } catch (GLib.Error e) { warning (e.message);+ return false; }+ return true; } @@ -206,29 +191,18 @@ class BackgroundSelection : FontDisplay { file = background_images.nth (active_box - 1).data; // Fixa: check bounds bg = new GlyphBackgroundImage (file); tb = MainWindow.get_tab_bar ();- cut_background_canvas = new CutBackgroundCanvas (glyph); bg.reset_scale (glyph); - cut_background_canvas.set_background_image (bg); glyph.set_background_visible (true); MainWindow.get_current_glyph ().set_background_image (bg); tb.select_tab_name (MainWindow.get_current_glyph ().get_name ());- - //tb.select_tab_name (glyph.get_name ());- //tb.close_display (this);- - //tb.add_tab (cut_background_canvas, 110, false);-- cut_background_canvas.set_show_help_lines (false);- cut_background_canvas.set_background_visible (true); zoom_background = MainWindow.get_tool ("zoom_background_image"); zoom_background.select_action (zoom_background); MainWindow.get_toolbox ().select_tool_by_name ("cut_background");- } private void add_unique_background (string file) {@@ -334,14 +308,4 @@ class BackgroundSelection : FontDisplay { } -class CutBackgroundCanvas : Glyph {- Glyph glyph;-- public CutBackgroundCanvas (Glyph g) {- base ("Background");- glyph = g;- redraw_help_lines ();- }-}- }@@ -54,14 +54,13 @@ class BackgroundTool : Tool { press_action.connect((self, b, x, y) => { Glyph g = MainWindow.get_current_glyph (); GlyphBackgroundImage? bg = g.get_background_image ();-- bool selection = MainWindow.get_current_display () is CutBackgroundCanvas; -- if (!selection) {- if (bg == null) return;- ((!)bg).handler_press (x, y);+ + if (bg == null) {+ return; } + ((!)bg).handler_press (x, y);+ begin_x = x; begin_y = y; @@ -80,7 +79,9 @@ class BackgroundTool : Tool { Glyph g = MainWindow.get_current_glyph (); GlyphBackgroundImage? bg = g.get_background_image (); - if (bg == null) return;+ if (bg == null) {+ return;+ } img_offset_x = ((!)bg).img_offset_x; img_offset_y = ((!)bg).img_offset_y;@@ -96,16 +97,11 @@ class BackgroundTool : Tool { }); draw_action.connect ((self, cairo_context, glyph) => {- bool selection; Glyph g = MainWindow.get_current_glyph (); GlyphBackgroundImage? background_image = g.get_background_image (); if (background_image == null) return; - selection = MainWindow.get_current_display () is CutBackgroundCanvas;- - if (!selection) {- ((!) background_image).draw_handle (cairo_context, glyph);- }+ ((!) background_image).draw_handle (cairo_context, glyph); }); } @@ -119,7 +115,7 @@ class BackgroundTool : Tool { if (background_image == null) return; bg.handler_move (x, y);- + if (!(move_bg || resize_bg)) return; dx = x - begin_x;@@ -81,7 +81,7 @@ class CutBackgroundTool : Tool { cr.set_line_width (2.0); cr.set_source_rgba (0, 0, 1, 0.3); cr.rectangle (fmin (x1, x2), fmin (y1, y2), fabs (x1 - x2), fabs (y1 - y2));- cr.fill_preserve ();+ cr.stroke (); cr.restore (); } });@@ -157,8 +157,8 @@ class CutBackgroundTool : Tool { ty *= g.view_zoom; tx *= g.view_zoom; - vx = g.path_coordinate_x (tx) - g.path_coordinate_x (x1); - vy = g.path_coordinate_y (ty) - g.path_coordinate_y (y1);+ vx = g.path_coordinate_x (tx) - g.path_coordinate_x (fmin (x1, x2)); + vy = g.path_coordinate_y (ty) - g.path_coordinate_y (fmin (y1, y2)); x = (int) (vx / bg.img_scale_x); y = (int) (-vy / bg.img_scale_y);@@ -174,14 +174,6 @@ class CutBackgroundTool : Tool { cr.scale (bg.img_scale_x, bg.img_scale_y); - /*- cr.save ();- cr.set_source_rgba (1, 1, 1, 1);- cr.rectangle (0, 0, w, h);- cr.fill ();- cr.restore ();- */- cr.set_source_surface (sg, x, y); cr.paint (); @@ -1077,7 +1077,8 @@ class Font : GLib.Object { } private void parse_background_scale (Glyph g, Xml.Node* node) {- GlyphBackgroundImage img = new GlyphBackgroundImage ();+ GlyphBackgroundImage img;+ GlyphBackgroundImage? new_img = null; string attr_name; string attr_content;@@ -1087,10 +1088,17 @@ class Font : GLib.Object { attr_content = prop->children->content; if (attr_name == "src") {- img = new GlyphBackgroundImage (attr_content);- g.set_background_image (img);+ new_img = new GlyphBackgroundImage (attr_content);+ g.set_background_image ((!) new_img); } }+ + if (new_img == null) {+ warning ("No source for image found.");+ return;+ }+ + img = (!) new_img; for (Xml.Attr* prop = node->properties; prop != null; prop = prop->next) { attr_name = prop->name;@@ -135,7 +135,7 @@ class Glyph : FontDisplay { } } - ((!) p).set_selected (true);+ // ((!) p).set_selected (true); active_paths.append ((!) p); }@@ -237,8 +237,15 @@ class Glyph : FontDisplay { } } - public void set_background_image (GlyphBackgroundImage bg) {+ public void set_background_image (GlyphBackgroundImage? b) { double default_img_offset_x, default_img_offset_y;+ GlyphBackgroundImage bg;+ + if (b == null) {+ background_image = null;+ }+ + bg = (!) b; default_img_offset_x = -get_width () / 2; default_img_offset_y = get_height () / 4;@@ -1044,7 +1051,6 @@ class Glyph : FontDisplay { if (p.is_editable ()) { r = true; p.close ();- redraw_path_region (p); } } @@ -1057,6 +1063,8 @@ class Glyph : FontDisplay { delete_invisible_paths (); + queue_draw_area (0, 0, allocation.width, allocation.height);+ return r; } @@ -1065,8 +1073,9 @@ class Glyph : FontDisplay { foreach (var p in path_list) { p.set_editable (true);- redraw_path_region (p); }+ + queue_draw_area (0, 0, allocation.width, allocation.height); } public void redraw_path_region (Path p) {@@ -1326,8 +1335,6 @@ class Glyph : FontDisplay { // plot_outline (cr); - cr.save ();- baseline = get_line ("baseline").pos; left = get_line ("left").pos; @@ -1342,16 +1349,14 @@ class Glyph : FontDisplay { if (new_point_on_path != null) { Path.draw_edit_point_center ((!) new_point_on_path, cr); }-- cr.restore (); } private void draw_zoom_area(Context cr) { cr.save (); cr.set_line_width (2.0);- cr.set_source_rgba (1, 0, 0, 0.3);+ cr.set_source_rgba (0, 0, 1, 0.3); cr.rectangle (Math.fmin (zoom_x1, zoom_x2), Math.fmin (zoom_y1, zoom_y2), Math.fabs (zoom_x1 - zoom_x2), Math.fabs (zoom_y1 - zoom_y2));- cr.fill_preserve ();+ cr.stroke (); cr.restore (); } @@ -1403,6 +1408,12 @@ class Glyph : FontDisplay { cmp.restore (); } + cmp.save ();+ cmp.scale (view_zoom, view_zoom);+ cmp.translate (-view_offset_x, -view_offset_y);+ draw_path (cmp); // This does mess up scale (sometimes) for unknown reasons + cmp.restore ();+ cmp.save (); tool = MainWindow.get_toolbox ().get_current_tool (); tool.draw_action (tool, cmp, this);@@ -1413,12 +1424,6 @@ class Glyph : FontDisplay { draw_zoom_area (cmp); cmp.restore (); }- - cmp.save ();- cmp.scale (view_zoom, view_zoom);- cmp.translate (-view_offset_x, -view_offset_y);- draw_path (cmp); // This does mess up scale for some unknown reason - cmp.restore (); cr.save (); cr.set_source_surface (ps, 0, 0);@@ -365,7 +365,7 @@ class GlyphBackgroundImage { int prev_handle = active_handle; if (is_over_rotate (nx, ny)) {- active_handle = 2; + active_handle = 2; } else if (is_over_resize (nx, ny)) { active_handle = 1; } else {@@ -755,6 +755,7 @@ class Path { public bool is_over_boundry_precision (double x, double y, double p) { if (unlikely (ymin == double.MAX)) { warning (@"no bounding box. length ($(points.length ()))");+ update_region_boundries (); } return (ymin - p <= y <= ymax + p) && (xmin - p <= x <= xmax + p);@@ -65,8 +65,6 @@ class PenTool : Tool { press_action.connect ((self, b, x, y) => { last_point_x = x; last_point_y = y;- - precision = 1; press (b, x, y); });@@ -108,17 +106,26 @@ class PenTool : Tool { key_release_action.connect ((self, keyval) => { if (keyval == Key.SHIFT_LEFT) { adjust_precision = false;- precision = 1.0 / Path.distance (adjust_precision_begin_x, last_point_x, adjust_precision_begin_y, last_point_y);+ set_precision (1.0 / Path.distance (adjust_precision_begin_x, last_point_x, adjust_precision_begin_y, last_point_y)); precision *= 30; if (precision > 1) {- precision = 1;+ set_precision (precision); } } }); }- + + public double get_precision () {+ return precision;+ }+ + public void set_precision (double p) {+ precision = p;+ MainWindow.get_toolbox ().precision.set_value_round (p, false, false);+ }+ public void move (double x, double y) { Glyph glyph = MainWindow.get_current_glyph (); EditPoint ep;@@ -35,6 +35,9 @@ class SpinButton : Tool { double begin_y = 0; double begin_value = 0; + double max = 9.999;+ double min = 0;+ public SpinButton (string? name = null, string tip = "", unichar key = '\0', uint modifier_flag = 0) { base (null , tip, key, modifier_flag); @@ -78,6 +81,14 @@ class SpinButton : Tool { }); } + public void set_max (double max) {+ this.max = max;+ }++ public void set_min (double min) {+ this.min = min;+ }+ public void increase () { if (deka == 9 && deci == 9 && centi == 9 && milli == 9) { return;@@ -100,6 +111,10 @@ class SpinButton : Tool { deci = 0; } + if (get_value () > max) {+ set_value_round (max, false);+ }+ new_value_action (this); } @@ -128,21 +143,46 @@ class SpinButton : Tool { if (get_value () < 0.05) { // lower limit set_value_round (0.05); }- ++ if (get_value () < min) {+ set_value_round (min, false);+ }+ new_value_action (this); } - public void set_value (string v) - requires (v.char_count () >= 5)- {+ public void set_value (string new_value, bool check_boundries = true, bool emit_signal = true) {+ string v = new_value;+ + while (!(v.char_count () >= 5)) {+ if (v.index_of (".") == -1) {+ v += ".";+ } else {+ v += "0";+ }+ + return;+ }+ deka = (int8) int.parse (v.substring (0, 1)); deci = (int8) int.parse (v.substring (2, 1)); centi = (int8) int.parse (v.substring (3, 1)); milli = (int8) int.parse (v.substring (4, 1));- new_value_action (this);+ + if (emit_signal) {+ new_value_action (this);+ }+ + if (check_boundries && get_value () > max) {+ set_value_round (max, false);+ }++ if (check_boundries && get_value () < min) {+ set_value_round (min, false);+ } } - public void set_value_round (double v) {+ public void set_value_round (double v, bool check_boundries = true, bool emit_signal = true) { int8 m; v += 0.005;@@ -151,7 +191,7 @@ class SpinButton : Tool { if (v < 0.001) v = 0.001; m = milli; // ignore milli value- set_value (@"$v");+ set_value (@"$v", check_boundries, emit_signal); milli = m; } @@ -42,6 +42,7 @@ class Toolbox : DrawingArea { Tool press_tool = new Tool (null); // activate the pressed button on release public SpinButton background_scale = new SpinButton ();+ public SpinButton precision; public Toolbox (GlyphCanvas main_glyph_canvas) { glyph_canvas = main_glyph_canvas;@@ -92,14 +93,14 @@ class Toolbox : DrawingArea { // Draw tool modifiers Tool new_point = new Tool ("new_point", "Add new points", 'a');- new_point.select_action.connect((self) => {+ new_point.select_action.connect ((self) => { select_draw_tool (); }); draw_tool_modifiers.add_tool (new_point); Tool insert_point_on_path = new Tool ("insert_point_on_path", "Add new point on path", 'n');- insert_point_on_path.select_action.connect((self) => {+ insert_point_on_path.select_action.connect ((self) => { select_draw_tool (); pen_tool.begin_from_new_point_on_path (); });@@ -107,7 +108,7 @@ class Toolbox : DrawingArea { if (Supplement.experimental) { Tool new_point_on_path = new Tool ("new_point_on_path", "Begin new path from point on path", 'n');- new_point_on_path.select_action.connect((self) => {+ new_point_on_path.select_action.connect ((self) => { select_draw_tool (); pen_tool.begin_from_new_point_on_path (); });@@ -115,7 +116,7 @@ class Toolbox : DrawingArea { } Tool tie_editpoint_tool = new Tool ("tie_point", "Tie curve handles for selected edit point", 'w');- tie_editpoint_tool.select_action.connect((self) => {+ tie_editpoint_tool.select_action.connect ((self) => { EditPoint ep; bool tie; @@ -144,13 +145,28 @@ class Toolbox : DrawingArea { select_draw_tool (); }); draw_tool_modifiers.add_tool (erase_tool); - ++ // adjust precision+ precision = new SpinButton ("precision", "Set precision");+ precision.set_value_round (1);++ precision.new_value_action.connect ((self) => {+ pen_tool.set_precision (self.get_value ());+ select_tool (precision);+ + });+ + precision.set_min (0.001);+ precision.set_max (1);+ + draw_tool_modifiers.add_tool (precision);+ // 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');- reverse_path_tool.select_action.connect((self) => {+ reverse_path_tool.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); foreach (Path p in g.active_paths) {@@ -162,7 +178,7 @@ class Toolbox : DrawingArea { path_tool_modifiers.add_tool (reverse_path_tool); Tool move_layer = new Tool ("move_layer", "Move to path to bottom layer", 'd');- move_layer.select_action.connect((self) => {+ move_layer.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); foreach (Path p in g.active_paths) {@@ -174,7 +190,7 @@ class Toolbox : DrawingArea { // Character set tools Tool full_unicode = new Tool ("utf_8", "Show full unicode characters set", 'a', CTRL);- full_unicode.select_action.connect((self) => {+ full_unicode.select_action.connect ((self) => { MainWindow.get_tab_bar ().add_unique_tab (new OverView (), 75, false); OverView o = MainWindow.get_overview (); GlyphRange gr = new GlyphRange ();@@ -185,7 +201,7 @@ class Toolbox : DrawingArea { characterset_tools.add_tool (full_unicode); Tool custom_character_set = new Tool ("custom_character_set", "Show default characters set", 'r', CTRL);- custom_character_set.select_action.connect((self) => {+ custom_character_set.select_action.connect ((self) => { MainWindow.get_tab_bar ().add_unique_tab (new OverView (), 75, false); OverView o = MainWindow.get_overview (); GlyphRange gr = new GlyphRange ();@@ -196,7 +212,7 @@ class Toolbox : DrawingArea { characterset_tools.add_tool (custom_character_set); Tool avalilable_characters = new Tool ("available_characters", "Show characters in font", 'd', CTRL);- avalilable_characters.select_action.connect((self) => {+ avalilable_characters.select_action.connect ((self) => { MainWindow.get_tab_bar ().add_unique_tab (new OverView (), 75, false); OverView o = MainWindow.get_overview (); o.display_all_available_glyphs ();@@ -205,7 +221,7 @@ class Toolbox : DrawingArea { characterset_tools.add_tool (avalilable_characters); Tool delete_glyph = new Tool ("delete_selected_glyph", "Delete selected glyph or path");- delete_glyph.select_action.connect((self) => {+ delete_glyph.select_action.connect ((self) => { OverView o = MainWindow.get_overview (); if (MainWindow.get_current_display () is OverView) {@@ -260,7 +276,7 @@ class Toolbox : DrawingArea { // help lines, grid and other guidlines Tool help_lines = new Tool ("help_lines", "Show help lines", 'l');- help_lines.select_action.connect((self) => {+ help_lines.select_action.connect ((self) => { bool h; h = glyph_canvas.get_current_glyph ().get_show_help_lines (); glyph_canvas.get_current_glyph ().set_show_help_lines (!h);@@ -271,7 +287,7 @@ class Toolbox : DrawingArea { guideline_tools.add_tool (help_lines); Tool xheight_help_lines = new Tool ("show_xheight_helplines", "Show help lines for x-height and baseline", 'x');- xheight_help_lines.select_action.connect((self) => {+ xheight_help_lines.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); bool v = !g.get_xheight_lines_visible (); g.set_xheight_lines_visible (v);@@ -286,7 +302,7 @@ class Toolbox : DrawingArea { guideline_tools.add_tool (xheight_help_lines); Tool background_help_lines = new Tool ("background_help_lines", "Show help lines at top and bottom margin", 't');- background_help_lines.select_action.connect((self) => {+ background_help_lines.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); bool v = !g.get_margin_lines_visible (); g.set_margin_lines_visible (v);@@ -304,21 +320,21 @@ class Toolbox : DrawingArea { // Zoom tools Tool zoom_in = new Tool ("zoom_in", "zoom in", '+', CTRL);- zoom_in.select_action.connect((self) => {+ zoom_in.select_action.connect ((self) => { zoom_tool.store_current_view (); glyph_canvas.get_current_display ().zoom_in (); }); view_tools.add_tool (zoom_in); Tool zoom_out = new Tool ("zoom_out", "Zoom out", '-', CTRL);- zoom_out.select_action.connect((self) => {+ zoom_out.select_action.connect ((self) => { zoom_tool.store_current_view (); glyph_canvas.get_current_display ().zoom_out (); }); view_tools.add_tool (zoom_out); Tool reset_zoom = new Tool ("zoom_1_1", "Zoom to scale 1:1", '0', CTRL);- reset_zoom.select_action.connect((self) => {+ reset_zoom.select_action.connect ((self) => { zoom_tool.store_current_view (); glyph_canvas.get_current_display ().reset_zoom (); glyph_canvas.queue_draw_area(0, 0, glyph_canvas.allocation.width, glyph_canvas.allocation.height);@@ -378,10 +394,6 @@ class Toolbox : DrawingArea { GlyphBackgroundImage? img = g.get_background_image (); double s = sb.get_value (); - if (MainWindow.get_current_display () is CutBackgroundCanvas) {- return;- }- if (img != null) { ((!)img).set_img_scale (s, s); }@@ -400,7 +412,7 @@ class Toolbox : DrawingArea { this.cut_background = cut_background; Tool show_bg = new Tool ("show_background", "Show background image");- show_bg.select_action.connect((self) => {+ show_bg.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); g.set_background_visible (!g.get_background_visible ()); MainWindow.get_glyph_canvas ().redraw ();@@ -408,7 +420,7 @@ class Toolbox : DrawingArea { background_tools.add_tool (show_bg); Tool background_size_to_boundries = new Tool ("size_to_boundries", "Fit image between margin lines", 'F', SHIFT);- background_size_to_boundries.select_action.connect((self) => {+ background_size_to_boundries.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); GlyphBackgroundImage? bg = g.get_background_image (); GlyphBackgroundImage b = (!) bg;@@ -456,11 +468,11 @@ class Toolbox : DrawingArea { SpinButton background_contrast = new SpinButton ("background_contrast", "Set background contrast"); background_contrast.set_value_round (1); - background_contrast.new_value_action.connect((self) => {+ background_contrast.new_value_action.connect ((self) => { background_contrast.select_action (self); }); - background_contrast.select_action.connect((self) => { + background_contrast.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); GlyphBackgroundImage? bg = g.get_background_image (); GlyphBackgroundImage b;@@ -477,11 +489,11 @@ class Toolbox : DrawingArea { SpinButton background_threshold = new SpinButton ("background_threshold", "Set threshold"); background_threshold.set_value_round (1); - background_threshold.new_value_action.connect((self) => {+ background_threshold.new_value_action.connect ((self) => { background_threshold.select_action (self); }); - background_threshold.select_action.connect((self) => { + background_threshold.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); GlyphBackgroundImage? bg = g.get_background_image (); GlyphBackgroundImage b;