The Birdfont Source Code


All Repositories / birdfont.git / commitdiff – RSS feed

Speed optimizations for background images

These changes was commited to the Birdfont repository Tue, 08 Dec 2015 18:55:20 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
[Tue, 08 Dec 2015 18:55:20 +0000]

Updated Files

libbirdfont/BackgroundImage.vala
libbirdfont/ScaledBackgroundPart.vala
libbirdfont/ScaledBackgrounds.vala
libbirdfont/ScaledImage.vala
--- a/libbirdfont/BackgroundImage.vala +++ b/libbirdfont/BackgroundImage.vala @@ -46,6 +46,8 @@ private Gee.ArrayList<TracedPoint> start_points = new Gee.ArrayList<TracedPoint> (); public signal void updated (); + + private ScaledBackgrounds? scaled = null; public double img_offset_x { get { return img_x + Glyph.xc (); } @@ -113,6 +115,14 @@ return bg; } + + public ScaledBackgrounds get_scaled_backgrounds () { + if (scaled == null) { + scaled = new ScaledBackgrounds ((ImageSurface) get_rotated_image ()); + } + + return (!) scaled; + } public void add_selection (BackgroundSelection bs) { selections.add (bs); @@ -160,7 +170,7 @@ if (background_image == null) { background_image = new ImageSurface.from_png (path); - original_image = new ImageSurface.from_png (path); + original_image = new ImageSurface.from_png (path); } return (!) original_image; @@ -387,7 +397,9 @@ img_offset_y = g.get_line ("top").pos; } - public void draw (Context cr, WidgetAllocation allocation, double view_offset_x, double view_offset_y, double view_zoom) { + public void draw (Context cr, WidgetAllocation allocation, + double view_offset_x, double view_offset_y, double view_zoom) { + double scale_x, scale_y; double image_scale_x, image_scale_y; ImageSurface s; @@ -417,29 +429,50 @@ image_scale_y = img_scale_y * ((double) rotated_image.get_height () / s.get_height ()); } - st = new Surface.similar (s, s.get_content (), allocation.width, allocation.height); - ct = new Context (st); - ct.save (); + // FIXME: rotated and contrast + ScaledBackgrounds backgrounds = get_scaled_backgrounds (); + ScaledBackground scaled = backgrounds.get_image (view_zoom * img_scale_x); // FIXME: y - ct.set_source_rgba (1, 1, 1, 1); - ct.rectangle (0, 0, allocation.width, allocation.height); - ct.fill (); + ScaledBackgroundPart part; + double part_scale_x = view_zoom * image_scale_x; + double part_scale_y = view_zoom * image_scale_y; + + double part_offset_x = img_offset_x - view_offset_x; + part_offset_x *= view_zoom; + part_offset_x = -part_offset_x; + + double part_offset_y = img_offset_y - view_offset_y; + part_offset_y *= view_zoom; + part_offset_y = -part_offset_y; + + part = scaled.get_part (part_offset_x, part_offset_y, + allocation.width, allocation.height); - // scale both canvas and image at the same time scale_x = view_zoom * image_scale_x; scale_y = view_zoom * image_scale_y; - ct.scale (scale_x, scale_y); - ct.translate (-view_offset_x / image_scale_x, -view_offset_y / image_scale_y); + scale_x /= part.get_scale (); + scale_y /= part.get_scale (); - ct.set_source_surface (s, img_offset_x / image_scale_x, img_offset_y / image_scale_y); + ImageSurface scaled_image; + Context scaled_context; + scaled_image = new ImageSurface (Format.ARGB32, allocation.width, allocation.height); + scaled_context = new Context (scaled_image); - ct.paint (); - ct.restore (); + scaled_context.scale (scale_x, scale_y); + double scaled_x = part.offset_x; + double scaled_y = part.offset_y; + + scaled_x += view_zoom * (img_offset_x / scale_x - view_offset_x / scale_x); + scaled_y += view_zoom * (img_offset_y / scale_y - view_offset_y / scale_y); + + scaled_context.set_source_surface (part.get_image (), scaled_x, scaled_y); + scaled_context.paint (); + // add it cr.save (); - cr.set_source_surface (st, 0, 0); + cr.set_source_surface (scaled_image, 0, 0); cr.paint (); cr.restore (); }
--- /dev/null +++ b/libbirdfont/ScaledBackgroundPart.vala @@ -1,1 +1,44 @@ + /* + Copyright (C) 2015 Johan Mattsson + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + */ + + using Cairo; + using Math; + using Gee; + + namespace BirdFont { + + public class ScaledBackgroundPart : GLib.Object { + public double scale; + public int offset_x; + public int offset_y; + public ImageSurface image; + + public ScaledBackgroundPart (ImageSurface image, double scale, int offset_x, int offset_y) { + this.image = image; + this.scale = scale; + this.offset_x = offset_x; + this.offset_y = offset_y; + } + + public double get_scale () { + return scale; + } + + public ImageSurface get_image () { + return image; + } + } + + }
--- /dev/null +++ b/libbirdfont/ScaledBackgrounds.vala @@ -1,1 +1,65 @@ + /* + Copyright (C) 2015 Johan Mattsson + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + */ + + using Cairo; + using Math; + using Gee; + + namespace BirdFont { + + public class ScaledBackgrounds : GLib.Object { + ImageSurface original; + ArrayList<ScaledBackground> scaled; + + public ScaledBackgrounds (ImageSurface original) { + this.original = original; + scaled = new ArrayList<ScaledBackground> (); + + ScaledBackground image = scale (0.01); + scaled.add (image); + + for (double scale_factor = 0.1; scale_factor <= 1; scale_factor += 0.1) { + image = scale (scale_factor); + scaled.add (image); + } + } + + public ScaledBackground get_image (double scale) { + foreach (ScaledBackground image in scaled) { + if (image.get_scale () < scale) { + continue; + } + + return image; + } + + return scaled.get (scaled.size - 1); + } + + private ScaledBackground scale (double scale_factor) { + ImageSurface scaled_image; + int width = (int) (scale_factor * original.get_width ()); + int height = (int) (scale_factor * original.get_height ()); + scaled_image = new ImageSurface (Format.ARGB32, width, height); + Context context = new Context (scaled_image); + context.scale (scale_factor, scale_factor); + context.set_source_surface (original, 0, 0); + context.paint (); + + return new ScaledBackground (scaled_image, scale_factor); + } + } + + }
--- /dev/null +++ b/libbirdfont/ScaledImage.vala @@ -1,1 +1,129 @@ + /* + Copyright (C) 2015 Johan Mattsson + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + */ + + using Cairo; + using Math; + using Gee; + + namespace BirdFont { + + public class ScaledBackground : GLib.Object { + ImageSurface image; + double scale; + ArrayList<ImageSurface> parts; + int size; + int part_width; + int part_height; + + public ScaledBackground (ImageSurface image, double scale) { + this.image = image; + this.scale = scale; + parts = new ArrayList<ImageSurface> (); + + size = 10; + part_width = image.get_width () / size; + part_height = image.get_height () / size; + + for (int y = 0; y < size; y++) { + for (int x = 0; x < size; x++) { + ImageSurface next_part; + next_part = new ImageSurface (Format.RGB24, part_width, part_height); + Context context = new Context (next_part); + context.set_source_surface (image, -x * part_width, -y * part_width); + context.paint (); + parts.add (next_part); + } + } + } + + public double get_scale () { + return scale; + } + + public ImageSurface get_image () { + return image; + } + + ImageSurface? get_part_at (int x, int y) { + int index = y * size + x; + + if (x >= size || x < 0) { + return null; + } + + if (y >= size || y < 0) { + return null; + } + + if (unlikely (!(0 <= index < parts.size))) { + warning (@"No part at index: $x, $y"); + return null; + } + + return parts.get (index); + } + + public ScaledBackgroundPart get_part (double offset_x, double offset_y, + int width, int height) { + + double image_width = part_width * size; + double image_height = part_height * size; + + int start_x = (int) ((offset_x / image_width) * size) - 1; + int start_y = (int) ((offset_y / image_height) * size) - 1; + int stop_x = (int) (((offset_x + width) / image_width) * size) + 2; + int stop_y = (int) (((offset_y + height) / image_height) * size) + 2; + + int assembled_width = (int) ((size + 2) * image_width); + int assembled_height = (int) ((size + 2) * image_height); + image = new ImageSurface (Format.RGB24, assembled_width, assembled_height); + Context context = new Context (image); + + int start_offset_x = start_x * part_width; + int start_offset_y = start_y * part_height; + + if (start_offset_x > 0) { + start_x = -1; + start_offset_x = start_x * part_width; + } + + if (start_offset_y > 0) { + start_y = -1; + start_offset_y = start_y * part_height; + } + + for (int y = start_y; y < stop_y; y++) { + for (int x = start_x; x < stop_x; x++) { + ImageSurface? part = get_part_at (x, y); + + if (part != null) { + context.save (); + + context.set_source_surface ((!) part, + (x - start_x) * part_width, + (y - start_y) * part_height); + + context.paint (); + context.restore (); + } + } + } + + return new ScaledBackgroundPart (image, scale, + start_offset_x, start_offset_y); + } + } + + }