1/** 2 * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) 3 * 4 * This file is part of Akira. 5 * 6 * Akira is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 11 * Akira is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 16 * You should have received a copy of the GNU General Public License 17 * along with Akira. If not, see <https://www.gnu.org/licenses/>. 18 * 19 * Authored by: Alessandro "Alecaddd" Castellani <castellani.ale@gmail.com> 20 */ 21 22using Akira.Lib.Components; 23 24/** 25 * Generate a simple Image item. 26 */ 27public class Akira.Lib.Items.CanvasImage : Goo.CanvasImage, Akira.Lib.Items.CanvasItem { 28 public Gee.ArrayList<Component> components { get; set; } 29 30 public Items.CanvasArtboard? artboard { get; set; } 31 32 // CanvasImage unique attributes. 33 public Lib.Managers.ImageManager manager { get; set; } 34 private Gdk.Pixbuf original_pixbuf; 35 36 public CanvasImage ( 37 double _x, 38 double _y, 39 Lib.Managers.ImageManager _manager, 40 Goo.CanvasItem? _parent, 41 Items.CanvasArtboard? _artboard 42 ) { 43 parent = _artboard != null ? _artboard : _parent; 44 artboard = _artboard; 45 46 // Set the ImageManager. 47 manager = _manager; 48 49 // Create the image item. 50 x = y = 0; 51 width = height = 1; 52 scale_to_fit = true; 53 init_position (this, _x, _y); 54 55 // Add the newly created item to the Canvas or Artboard. 56 parent.add_child (this, -1); 57 58 // Initialize the imported image. 59 init_pixbuf (); 60 61 // Force the generation of the item bounds on creation. 62 Goo.CanvasBounds bounds; 63 this.get_bounds (out bounds); 64 65 // Add all the components that this item uses. 66 components = new Gee.ArrayList<Component> (); 67 components.add (new Name (this)); 68 components.add (new Coordinates (this)); 69 components.add (new Opacity (this)); 70 components.add (new Rotation (this)); 71 components.add (new Size (this)); 72 components.add (new Flipped (this)); 73 components.add (new Layer ()); 74 75 check_add_to_artboard (this); 76 77 ((Lib.Canvas) canvas).window.event_bus.detect_image_size_change.connect (check_resize_pixbuf); 78 } 79 80 private void init_pixbuf () { 81 // Load the pixbuf at full resolution to properly define the size ratio of the item. 82 manager.get_pixbuf.begin (-1, -1, (obj, res) => { 83 try { 84 original_pixbuf = manager.get_pixbuf.end (res); 85 pixbuf = original_pixbuf; 86 87 // Define the item's size based on the images size. 88 size.width = original_pixbuf.width; 89 size.height = original_pixbuf.height; 90 // Imported images should have their size ratio locked by default. 91 // Change the locked attribute after the size has been defined to let 92 // the Size component properly calculate the correct size ratio. 93 size.locked = true; 94 95 // Reset the size to a 2px initial value after the size ratio was properly defined 96 // in order to allow the user to decide the initial image size. We use 2px in order 97 // to avoid issues when dividing by the ratio in case of narrow images. 98 size.width = 2; 99 } catch (Error e) { 100 warning (e.message); 101 ((Lib.Canvas) canvas).window.event_bus.canvas_notification (e.message); 102 } 103 }); 104 } 105 106 /** 107 * Trigger the pixbuf resampling. 108 */ 109 public void check_resize_pixbuf () { 110 // Interrupt if this image isn't part of the selection. 111 if (!layer.selected) { 112 return; 113 } 114 115 // Interrupt if the size of the image didn't change. 116 if (size.width == manager.pixbuf.get_width () && size.height == manager.pixbuf.get_height ()) { 117 return; 118 } 119 120 resize_pixbuf ((int) size.width, (int) size.height); 121 } 122 123 /** 124 * Resample the pixbuf size. 125 * 126 * @param {int} w - The new width. 127 * @param {int} h - The new height. 128 * @param {bool} update - If the updated pixbuf size should be applied to the CanvasItem. 129 */ 130 public void resize_pixbuf (int w, int h, bool update = false) { 131 manager.get_pixbuf.begin (w, h, (obj, res) => { 132 try { 133 var _pixbuf = manager.get_pixbuf.end (res); 134 pixbuf = _pixbuf; 135 if (update) { 136 width = _pixbuf.get_width (); 137 height = _pixbuf.get_height (); 138 } 139 } catch (Error e) { 140 warning (e.message); 141 ((Lib.Canvas) canvas).window.event_bus.canvas_notification (e.message); 142 } 143 }); 144 } 145} 146