.
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