The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

ScaledImage.vala in /libbirdfont

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
Circle boundaries heads/master
1 /* 2 Copyright (C) 2015 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 using Cairo; 16 using Math; 17 using Gee; 18 19 namespace BirdFont { 20 21 public class ScaledBackground : GLib.Object { 22 ImageSurface image; 23 ImageSurface original; 24 ArrayList<ImageSurface> parts; 25 int size; 26 int part_width; 27 int part_height; 28 double scale; 29 30 public ScaledBackground (ImageSurface image, double scale) { 31 if (scale <= 0) { 32 warning ("scale <= 0"); 33 scale = 1; 34 } 35 36 original = image; 37 this.image = image; 38 this.scale = scale; 39 parts = new ArrayList<ImageSurface> (); 40 41 create_parts (); 42 } 43 44 public void rotate (double angle) { 45 image = BackgroundImage.rotate_image (original, angle); 46 create_parts (); 47 } 48 49 void create_parts () { 50 parts.clear (); 51 size = image.get_width () / 100; 52 53 if (size < 10) { 54 size = 10; 55 } 56 57 part_width = image.get_width () / size; 58 part_height = image.get_height () / size; 59 60 if (part_width < 1) { 61 part_width = 1; 62 } 63 64 if (part_height < 1) { 65 part_height = 1; 66 } 67 68 for (int y = 0; y < size; y++) { 69 for (int x = 0; x < size; x++) { 70 ImageSurface next_part; 71 next_part = new ImageSurface (Format.ARGB32, part_width, part_height); 72 Context context = new Context (next_part); 73 context.set_source_surface (image, -x * part_width, -y * part_width); 74 context.paint (); 75 parts.add (next_part); 76 } 77 } 78 } 79 80 public void set_scale (double s) { 81 scale = s; 82 } 83 84 public double get_scale () { 85 if (unlikely (scale == 0)) { 86 warning ("Zero scale."); 87 return 1; 88 } 89 90 return scale; 91 } 92 93 public ImageSurface get_image () { 94 return image; 95 } 96 97 ImageSurface? get_part_at (int x, int y) { 98 int index = y * size + x; 99 100 if (x >= size || x < 0) { 101 return null; 102 } 103 104 if (y >= size || y < 0) { 105 return null; 106 } 107 108 if (unlikely (!(0 <= index < parts.size))) { 109 warning (@"No part at index: $x, $y"); 110 return null; 111 } 112 113 return parts.get (index); 114 } 115 116 public ScaledBackgroundPart get_part (double offset_x, double offset_y, 117 int width, int height) { 118 119 if (width <= 0 || height <= 0) { 120 warning ("width <= 0 || height <= 0"); 121 scale = 1; 122 } 123 124 double image_width = part_width * size; 125 double image_height = part_height * size; 126 127 int start_x = (int) ((offset_x / image_width) * size); 128 int start_y = (int) ((offset_y / image_height) * size); 129 int stop_x = (int) (((offset_x + width) / image_width) * size) + 2; 130 int stop_y = (int) (((offset_y + height) / image_height) * size) + 2; 131 132 if (start_x < 0) { 133 start_x = 0; 134 } 135 136 if (start_y < 0) { 137 start_y = 0; 138 } 139 140 if (stop_x > size) { 141 stop_x = size; 142 } 143 144 if (stop_y > size) { 145 stop_y = size; 146 } 147 148 int assembled_width = (int) ((stop_x - start_x) * part_width); 149 int assembled_height = (int) ((stop_y - start_y) * part_height); 150 151 ImageSurface assembled_image = new ImageSurface (Format.ARGB32, assembled_width, assembled_height); 152 153 Context context = new Context (assembled_image); 154 155 int start_offset_x = start_x * part_width; 156 int start_offset_y = start_y * part_height; 157 158 for (int y = start_y; y < stop_y; y++) { 159 for (int x = start_x; x < stop_x; x++) { 160 ImageSurface? part = get_part_at (x, y); 161 162 if (part != null) { 163 context.save (); 164 165 context.set_source_surface ((!) part, 166 (x - start_x) * part_width, 167 (y - start_y) * part_height); 168 context.paint (); 169 170 context.restore (); 171 } 172 } 173 } 174 175 return new ScaledBackgroundPart (assembled_image, scale, 176 start_offset_x, start_offset_y); 177 } 178 } 179 180 } 181