GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 69.8% 164 / 0 / 235
Functions: 71.4% 25 / 0 / 35
Branches: 41.8% 61 / 0 / 146

shumate/shumate-map-source.c
Line Branch Exec Source
1 /*
2 * Copyright (C) 2010-2013 Jiri Techet <techet@gmail.com>
3 * Copyright (C) 2019 Marcus Lundblad <ml@update.uu.se>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /**
21 * ShumateMapSource:
22 *
23 * The base class for all map sources. Map sources fill [class@Tile] objects
24 * with images from various sources: a web API, for example, or a test pattern
25 * generated on demand.
26 *
27 * The most common map source is [class@RasterRenderer], which fetches tiles
28 * using a [class@TileDownloader].
29 */
30
31 #include "shumate-map-source.h"
32 #include "shumate-location.h"
33 #include "shumate-enum-types.h"
34
35 #include <math.h>
36
37 typedef struct {
38 char *id;
39 char *name;
40 char *license;
41 char *license_uri;
42 guint min_zoom_level;
43 guint max_zoom_level;
44 guint tile_size;
45 ShumateMapProjection projection;
46 } ShumateMapSourcePrivate;
47
48
4/6
shumate_map_source_class_intern_init:
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 5 not taken.
shumate_map_source_get_type:
✓ Branch 2 → 3 taken 11 times.
✓ Branch 2 → 7 taken 1255 times.
✓ Branch 4 → 5 taken 11 times.
✗ Branch 4 → 7 not taken.
1966 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ShumateMapSource, shumate_map_source, G_TYPE_OBJECT);
49
50 enum
51 {
52 PROP_ID = 1,
53 PROP_NAME,
54 PROP_LICENSE,
55 PROP_LICENSE_URI,
56 PROP_MIN_ZOOM_LEVEL,
57 PROP_MAX_ZOOM_LEVEL,
58 PROP_TILE_SIZE,
59 PROP_PROJECTION,
60 N_PROPERTIES
61 };
62
63 static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
64
65 enum
66 {
67 MODIFIED,
68 LAST_SIGNAL
69 };
70
71 static guint signals[LAST_SIGNAL] = { 0, };
72
73 static void
74 24 shumate_map_source_finalize (GObject *object)
75 {
76 24 ShumateMapSource *map_source = SHUMATE_MAP_SOURCE (object);
77 24 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
78
79
1/2
✓ Branch 2 → 3 taken 24 times.
✗ Branch 2 → 4 not taken.
24 g_clear_pointer (&priv->id, g_free);
80
2/2
✓ Branch 4 → 5 taken 18 times.
✓ Branch 4 → 6 taken 6 times.
24 g_clear_pointer (&priv->name, g_free);
81
2/2
✓ Branch 6 → 7 taken 18 times.
✓ Branch 6 → 8 taken 6 times.
24 g_clear_pointer (&priv->license, g_free);
82
2/2
✓ Branch 8 → 9 taken 18 times.
✓ Branch 8 → 10 taken 6 times.
24 g_clear_pointer (&priv->license_uri, g_free);
83
84 24 G_OBJECT_CLASS (shumate_map_source_parent_class)->finalize (object);
85 24 }
86
87 static void
88 ✗ shumate_map_source_get_property (GObject *object,
89 guint prop_id,
90 GValue *value,
91 GParamSpec *pspec)
92 {
93 ✗ ShumateMapSource *map_source = SHUMATE_MAP_SOURCE (object);
94
95 ✗ switch (prop_id)
96 {
97 ✗ case PROP_ID:
98 ✗ g_value_set_string (value, shumate_map_source_get_id (map_source));
99 ✗ break;
100
101 ✗ case PROP_NAME:
102 ✗ g_value_set_string (value, shumate_map_source_get_name (map_source));
103 ✗ break;
104
105 ✗ case PROP_LICENSE:
106 ✗ g_value_set_string (value, shumate_map_source_get_license (map_source));
107 ✗ break;
108
109 ✗ case PROP_LICENSE_URI:
110 ✗ g_value_set_string (value, shumate_map_source_get_license_uri (map_source));
111 ✗ break;
112
113 ✗ case PROP_MIN_ZOOM_LEVEL:
114 ✗ g_value_set_uint (value, shumate_map_source_get_min_zoom_level (map_source));
115 ✗ break;
116
117 ✗ case PROP_MAX_ZOOM_LEVEL:
118 ✗ g_value_set_uint (value, shumate_map_source_get_max_zoom_level (map_source));
119 ✗ break;
120
121 ✗ case PROP_TILE_SIZE:
122 ✗ g_value_set_uint (value, shumate_map_source_get_tile_size (map_source));
123 ✗ break;
124
125 ✗ case PROP_PROJECTION:
126 ✗ g_value_set_enum (value, shumate_map_source_get_projection (map_source));
127 ✗ break;
128
129 ✗ default:
130 ✗ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
131 }
132 ✗ }
133
134
135 static void
136 192 shumate_map_source_set_property (GObject *object,
137 guint prop_id,
138 const GValue *value,
139 GParamSpec *pspec)
140 {
141 192 ShumateMapSource *map_source = SHUMATE_MAP_SOURCE (object);
142
143
8/9
✓ Branch 2 → 3 taken 24 times.
✓ Branch 2 → 6 taken 24 times.
✓ Branch 2 → 9 taken 24 times.
✓ Branch 2 → 12 taken 24 times.
✓ Branch 2 → 15 taken 24 times.
✓ Branch 2 → 18 taken 24 times.
✓ Branch 2 → 21 taken 24 times.
✓ Branch 2 → 24 taken 24 times.
✗ Branch 2 → 27 not taken.
192 switch (prop_id)
144 {
145 24 case PROP_ID:
146 48 shumate_map_source_set_id (map_source,
147 24 g_value_get_string (value));
148 24 break;
149
150 24 case PROP_NAME:
151 48 shumate_map_source_set_name (map_source,
152 24 g_value_get_string (value));
153 24 break;
154
155 24 case PROP_LICENSE:
156 48 shumate_map_source_set_license (map_source,
157 24 g_value_get_string (value));
158 24 break;
159
160 24 case PROP_LICENSE_URI:
161 48 shumate_map_source_set_license_uri (map_source,
162 24 g_value_get_string (value));
163 24 break;
164
165 24 case PROP_MIN_ZOOM_LEVEL:
166 24 shumate_map_source_set_min_zoom_level (map_source,
167 g_value_get_uint (value));
168 24 break;
169
170 24 case PROP_MAX_ZOOM_LEVEL:
171 24 shumate_map_source_set_max_zoom_level (map_source,
172 g_value_get_uint (value));
173 24 break;
174
175 24 case PROP_TILE_SIZE:
176 24 shumate_map_source_set_tile_size (map_source,
177 g_value_get_uint (value));
178 24 break;
179
180 24 case PROP_PROJECTION:
181 48 shumate_map_source_set_projection (map_source,
182 24 g_value_get_enum (value));
183 24 break;
184
185 ✗ default:
186 ✗ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
187 }
188 192 }
189
190 static void
191 7 shumate_map_source_class_init (ShumateMapSourceClass *klass)
192 {
193 7 GObjectClass *object_class = G_OBJECT_CLASS (klass);
194
195 7 object_class->set_property = shumate_map_source_set_property;
196 7 object_class->get_property = shumate_map_source_get_property;
197 7 object_class->finalize = shumate_map_source_finalize;
198
199 7 klass->fill_tile_async = NULL;
200
201 /**
202 * ShumateMapSource:id:
203 *
204 * The id of the map source
205 */
206 14 obj_properties[PROP_ID] =
207 7 g_param_spec_string ("id", NULL, NULL,
208 NULL,
209 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
210
211 /**
212 * ShumateMapSource:name:
213 *
214 * The name of the map source
215 */
216 14 obj_properties[PROP_NAME] =
217 7 g_param_spec_string ("name", NULL, NULL,
218 NULL,
219 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
220
221 /**
222 * ShumateMapSource:license:
223 *
224 * The usage license of the map source
225 */
226 14 obj_properties[PROP_LICENSE] =
227 7 g_param_spec_string ("license", NULL, NULL,
228 NULL,
229 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
230
231 /**
232 * ShumateMapSource:license-uri:
233 *
234 * The usage license's uri for more information
235 */
236 14 obj_properties[PROP_LICENSE_URI] =
237 7 g_param_spec_string ("license-uri", NULL, NULL,
238 NULL,
239 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
240
241 /**
242 * ShumateMapSource:min-zoom-level:
243 *
244 * The minimum zoom level
245 */
246 14 obj_properties[PROP_MIN_ZOOM_LEVEL] =
247 7 g_param_spec_uint ("min-zoom-level", NULL, NULL,
248 0, 50, 0,
249 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
250
251 /**
252 * ShumateMapSource:max-zoom-level:
253 *
254 * The maximum zoom level
255 */
256 14 obj_properties[PROP_MAX_ZOOM_LEVEL] =
257 7 g_param_spec_uint ("max-zoom-level", NULL, NULL,
258 0, 50, 18,
259 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
260
261 /**
262 * ShumateMapSource:tile-size:
263 *
264 * The tile size of the map source
265 */
266 14 obj_properties[PROP_TILE_SIZE] =
267 7 g_param_spec_uint ("tile-size", NULL, NULL,
268 0, 2048, 256,
269 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
270
271 /**
272 * ShumateMapSource:projection:
273 *
274 * The map projection of the map source
275 */
276 14 obj_properties[PROP_PROJECTION] =
277 7 g_param_spec_enum ("projection", NULL, NULL,
278 SHUMATE_TYPE_MAP_PROJECTION,
279 SHUMATE_MAP_PROJECTION_MERCATOR,
280 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
281
282 7 g_object_class_install_properties (object_class,
283 N_PROPERTIES,
284 obj_properties);
285
286 /**
287 * ShumateMapSource::modified:
288 * @self: the [class@MapSource] emitting the signal
289 *
290 * Emitted when the source is modified in such a way that tiles previously filled by it should be refreshed.
291 *
292 * It is the [class@MapSource] implementation's responsibility to emit this signal when appropriate, such as when a
293 * data source or rendering parameter changes.
294 *
295 * Since: 1.7
296 */
297 14 signals[MODIFIED] =
298 7 g_signal_new ("modified",
299 G_OBJECT_CLASS_TYPE (object_class),
300 G_SIGNAL_RUN_LAST,
301 0, NULL, NULL,
302 g_cclosure_marshal_VOID__VOID,
303 G_TYPE_NONE,
304 0);
305 7 }
306
307 static double
308 296 map_size (ShumateMapSource *self, double zoom_level)
309 {
310 296 return shumate_map_source_get_column_count (self, zoom_level) * shumate_map_source_get_tile_size_at_zoom (self, zoom_level);
311 }
312
313
314 static void
315 24 shumate_map_source_init (ShumateMapSource *map_source)
316 {
317 24 }
318
319 /**
320 * shumate_map_source_get_id:
321 * @map_source: a #ShumateMapSource
322 *
323 * Gets map source's id.
324 *
325 * Returns: the map source's id.
326 */
327 const char *
328 74 shumate_map_source_get_id (ShumateMapSource *map_source)
329 {
330 74 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
331
332
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 74 times.
74 g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), NULL);
333
334 74 return priv->id;
335 }
336
337 /**
338 * shumate_map_source_set_id:
339 * @map_source: a #ShumateMapSource
340 * @id: an id
341 *
342 * Sets the map source's id.
343 */
344 void
345 24 shumate_map_source_set_id (ShumateMapSource *map_source,
346 const char *id)
347 {
348 24 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
349
350
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 24 times.
24 g_return_if_fail (SHUMATE_IS_MAP_SOURCE (map_source));
351
352
1/2
✓ Branch 6 → 7 taken 24 times.
✗ Branch 6 → 19 not taken.
24 if (g_strcmp0 (priv->id, id) != 0)
353 {
354
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 24 times.
24 g_free (priv->id);
355
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 24 times.
24 priv->id = g_strdup (id);
356
357 24 g_object_notify_by_pspec (G_OBJECT (map_source), obj_properties[PROP_ID]);
358 }
359 }
360
361 /**
362 * shumate_map_source_get_name:
363 * @map_source: a #ShumateMapSource
364 *
365 * Gets map source's name.
366 *
367 * Returns: the map source's name.
368 */
369 const char *
370 ✗ shumate_map_source_get_name (ShumateMapSource *map_source)
371 {
372 ✗ ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
373
374 ✗ g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), NULL);
375
376 ✗ return priv->name;
377 }
378
379 /**
380 * shumate_map_source_set_name:
381 * @map_source: a #ShumateMapSource
382 * @name: a name
383 *
384 * Sets the map source's name.
385 */
386 void
387 24 shumate_map_source_set_name (ShumateMapSource *map_source,
388 const char *name)
389 {
390 24 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
391
392
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 24 times.
24 g_return_if_fail (SHUMATE_IS_MAP_SOURCE (map_source));
393
394
2/2
✓ Branch 6 → 7 taken 18 times.
✓ Branch 6 → 19 taken 6 times.
24 if (g_strcmp0 (priv->name, name) != 0)
395 {
396
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 18 times.
18 g_free (priv->name);
397
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 18 times.
18 priv->name = g_strdup (name);
398
399 18 g_object_notify_by_pspec (G_OBJECT (map_source), obj_properties[PROP_NAME]);
400 }
401 }
402
403 /**
404 * shumate_map_source_get_license:
405 * @map_source: a #ShumateMapSource
406 *
407 * Gets map source's license.
408 *
409 * Returns: the map source's license.
410 */
411 const char *
412 ✗ shumate_map_source_get_license (ShumateMapSource *map_source)
413 {
414 ✗ ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
415
416 ✗ g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), NULL);
417
418 ✗ return priv->license;
419 }
420
421 /**
422 * shumate_map_source_set_license:
423 * @map_source: a #ShumateMapSource
424 * @license: the licence
425 *
426 * Sets the map source's license.
427 */
428 void
429 24 shumate_map_source_set_license (ShumateMapSource *map_source,
430 const char *license)
431 {
432 24 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
433
434
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 24 times.
24 g_return_if_fail (SHUMATE_IS_MAP_SOURCE (map_source));
435
436
2/2
✓ Branch 6 → 7 taken 18 times.
✓ Branch 6 → 19 taken 6 times.
24 if (g_strcmp0 (priv->license, license) != 0)
437 {
438
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 18 times.
18 g_free (priv->license);
439
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 18 times.
18 priv->license = g_strdup (license);
440
441 18 g_object_notify_by_pspec (G_OBJECT (map_source), obj_properties[PROP_LICENSE]);
442 }
443 }
444
445 /**
446 * shumate_map_source_get_license_uri:
447 * @map_source: a #ShumateMapSource
448 *
449 * Gets map source's license URI.
450 *
451 * Returns: the map source's license URI.
452 */
453 const char *
454 ✗ shumate_map_source_get_license_uri (ShumateMapSource *map_source)
455 {
456 ✗ ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
457
458 ✗ g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), NULL);
459
460 ✗ return priv->license_uri;
461 }
462
463 /**
464 * shumate_map_source_set_license_uri:
465 * @map_source: a #ShumateMapSource
466 * @license_uri: the licence URI
467 *
468 * Sets the map source's license URI.
469 */
470 void
471 24 shumate_map_source_set_license_uri (ShumateMapSource *map_source,
472 const char *license_uri)
473 {
474 24 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
475
476
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 24 times.
24 g_return_if_fail (SHUMATE_IS_MAP_SOURCE (map_source));
477
478
2/2
✓ Branch 6 → 7 taken 18 times.
✓ Branch 6 → 19 taken 6 times.
24 if (g_strcmp0 (priv->license_uri, license_uri) != 0)
479 {
480
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 18 times.
18 g_free (priv->license_uri);
481
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 18 times.
18 priv->license_uri = g_strdup (license_uri);
482
483 18 g_object_notify_by_pspec (G_OBJECT (map_source), obj_properties[PROP_LICENSE_URI]);
484 }
485 }
486
487 /**
488 * shumate_map_source_get_min_zoom_level:
489 * @map_source: a #ShumateMapSource
490 *
491 * Gets map source's minimum zoom level.
492 *
493 * Returns: the miminum zoom level this map source supports
494 */
495 guint
496 2 shumate_map_source_get_min_zoom_level (ShumateMapSource *map_source)
497 {
498 2 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
499
500
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
2 g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0);
501
502 2 return priv->min_zoom_level;
503 }
504
505 /**
506 * shumate_map_source_set_min_zoom_level:
507 * @map_source: a #ShumateMapSource
508 * @zoom_level: the minimal zoom level
509 *
510 * Sets the map source's minimal zoom level.
511 */
512 void
513 30 shumate_map_source_set_min_zoom_level (ShumateMapSource *map_source,
514 guint zoom_level)
515 {
516 30 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
517
518
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 30 times.
30 g_return_if_fail (SHUMATE_IS_MAP_SOURCE (map_source));
519
520
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 30 times.
30 if (priv->min_zoom_level != zoom_level)
521 {
522 ✗ priv->min_zoom_level = zoom_level;
523
524 ✗ g_object_notify_by_pspec (G_OBJECT (map_source), obj_properties[PROP_MIN_ZOOM_LEVEL]);
525 }
526 }
527
528 /**
529 * shumate_map_source_get_max_zoom_level:
530 * @map_source: a #ShumateMapSource
531 *
532 * Gets map source's maximum zoom level.
533 *
534 * Returns: the maximum zoom level this map source supports
535 */
536 guint
537 76 shumate_map_source_get_max_zoom_level (ShumateMapSource *map_source)
538 {
539 76 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
540
541
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 76 times.
76 g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0);
542
543 76 return priv->max_zoom_level;
544 }
545
546 /**
547 * shumate_map_source_set_max_zoom_level:
548 * @map_source: a #ShumateMapSource
549 * @zoom_level: the maximum zoom level
550 *
551 * Sets the map source's maximum zoom level.
552 */
553 void
554 30 shumate_map_source_set_max_zoom_level (ShumateMapSource *map_source,
555 guint zoom_level)
556 {
557 30 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
558
559
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 30 times.
30 g_return_if_fail (SHUMATE_IS_MAP_SOURCE (map_source));
560
561
1/2
✓ Branch 5 → 6 taken 30 times.
✗ Branch 5 → 7 not taken.
30 if (priv->max_zoom_level != zoom_level)
562 {
563 30 priv->max_zoom_level = zoom_level;
564
565 30 g_object_notify_by_pspec (G_OBJECT (map_source), obj_properties[PROP_MAX_ZOOM_LEVEL]);
566 }
567 }
568
569 /**
570 * shumate_map_source_get_tile_size:
571 * @map_source: a #ShumateMapSource
572 *
573 * Gets map source's tile size.
574 *
575 * Returns: the tile's size (width and height) in pixels for this map source
576 */
577 guint
578 ✗ shumate_map_source_get_tile_size (ShumateMapSource *map_source)
579 {
580 ✗ ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
581
582 ✗ g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0);
583
584 ✗ return priv->tile_size;
585 }
586
587 /**
588 * shumate_map_source_get_tile_size_at_zoom:
589 * @map_source: a #ShumateMapSource
590 * @zoom_level: a zoom level
591 *
592 * Gets the apparent size of the map tiles at the given fractional zoom level.
593 *
594 * As the map is zoomed in, a tile gets bigger and bigger until, at the next
595 * integer zoom level, it "splits" into four tiles at the next zoom level.
596 * Thus, the size increase follows an exponential curve, base 2.
597 *
598 * Returns: the tile's size (width and height) in pixels for this map source
599 * at this zoom level
600 */
601 double
602 296 shumate_map_source_get_tile_size_at_zoom (ShumateMapSource *map_source,
603 double zoom_level)
604 {
605 296 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
606
607
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 296 times.
296 g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0);
608
609 296 return priv->tile_size * pow (2.0, fmod (zoom_level, 1.0));
610 }
611
612 /**
613 * shumate_map_source_set_tile_size:
614 * @map_source: a #ShumateMapSource
615 * @tile_size: the tile size
616 *
617 * Sets the map source's tile size.
618 */
619 void
620 30 shumate_map_source_set_tile_size (ShumateMapSource *map_source,
621 guint tile_size)
622 {
623 30 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
624
625
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 30 times.
30 g_return_if_fail (SHUMATE_IS_MAP_SOURCE (map_source));
626
627
1/2
✓ Branch 5 → 6 taken 30 times.
✗ Branch 5 → 7 not taken.
30 if (priv->tile_size != tile_size)
628 {
629 30 priv->tile_size = tile_size;
630
631 30 g_object_notify_by_pspec (G_OBJECT (map_source), obj_properties[PROP_TILE_SIZE]);
632 }
633 }
634
635 /**
636 * shumate_map_source_get_projection:
637 * @map_source: a #ShumateMapSource
638 *
639 * Gets map source's projection.
640 *
641 * Returns: the map source's projection.
642 */
643 ShumateMapProjection
644 ✗ shumate_map_source_get_projection (ShumateMapSource *map_source)
645 {
646 ✗ ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
647
648 ✗ g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), SHUMATE_MAP_PROJECTION_MERCATOR);
649
650 ✗ return priv->projection;
651 }
652
653 /**
654 * shumate_map_source_set_projection:
655 * @map_source: a #ShumateMapSource
656 * @projection: a #ShumateMapProjection
657 *
658 * Sets the map source's projection.
659 */
660 void
661 24 shumate_map_source_set_projection (ShumateMapSource *map_source,
662 ShumateMapProjection projection)
663 {
664 24 ShumateMapSourcePrivate *priv = shumate_map_source_get_instance_private (map_source);
665
666
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 24 times.
24 g_return_if_fail (SHUMATE_IS_MAP_SOURCE (map_source));
667
668
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 24 times.
24 if (priv->projection != projection)
669 {
670 ✗ priv->projection = projection;
671
672 ✗ g_object_notify_by_pspec (G_OBJECT (map_source), obj_properties[PROP_PROJECTION]);
673 }
674 }
675
676 /**
677 * shumate_map_source_fill_tile_async:
678 * @self: a #ShumateMapSource
679 * @tile: a #ShumateTile
680 * @cancellable: (nullable): a #GCancellable
681 * @callback: a #GAsyncReadyCallback to execute upon completion
682 * @user_data: closure data for @callback
683 *
684 * Asynchronous version of shumate_map_source_fill_tile().
685 */
686 void
687 ✗ shumate_map_source_fill_tile_async (ShumateMapSource *self,
688 ShumateTile *tile,
689 GCancellable *cancellable,
690 GAsyncReadyCallback callback,
691 gpointer user_data)
692 {
693 ✗ g_return_if_fail (SHUMATE_IS_MAP_SOURCE (self));
694 ✗ g_return_if_fail (SHUMATE_IS_TILE (tile));
695 ✗ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
696
697 ✗ return SHUMATE_MAP_SOURCE_GET_CLASS (self)->fill_tile_async (self, tile, cancellable, callback, user_data);
698 }
699
700 /**
701 * shumate_map_source_fill_tile_finish:
702 * @self: a #ShumateMapSource
703 * @result: a #GAsyncResult provided to callback
704 * @error: a location for a #GError, or %NULL
705 *
706 * Gets the success value of a completed shumate_map_source_fill_tile_async()
707 * operation.
708 *
709 * Returns: %TRUE if the tile was filled with valid data, otherwise %FALSE
710 */
711 gboolean
712 ✗ shumate_map_source_fill_tile_finish (ShumateMapSource *self,
713 GAsyncResult *result,
714 GError **error)
715 {
716 ✗ g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (self), FALSE);
717 ✗ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
718
719 ✗ return SHUMATE_MAP_SOURCE_GET_CLASS (self)->fill_tile_finish (self, result, error);
720 }
721
722 /**
723 * shumate_map_source_get_x:
724 * @map_source: a #ShumateMapSource
725 * @zoom_level: the zoom level
726 * @longitude: a longitude
727 *
728 * Gets the x position on the map using this map source's projection.
729 * (0, 0) is located at the top left.
730 *
731 * Returns: the x position
732 */
733 double
734 74 shumate_map_source_get_x (ShumateMapSource *map_source,
735 double zoom_level,
736 double longitude)
737 {
738
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 74 times.
74 g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0.0);
739
740
1/2
✓ Branch 5 → 6 taken 74 times.
✗ Branch 5 → 7 not taken.
74 longitude = CLAMP (longitude, SHUMATE_MIN_LONGITUDE, SHUMATE_MAX_LONGITUDE);
741
742 /* FIXME: support other projections */
743 74 return ((longitude + 180.0) / 360.0) * map_size (map_source, zoom_level);
744 }
745
746 /**
747 * shumate_map_source_get_y:
748 * @map_source: a #ShumateMapSource
749 * @zoom_level: the zoom level
750 * @latitude: a latitude
751 *
752 * Gets the y position on the map using this map source's projection.
753 * (0, 0) is located at the top left.
754 *
755 * Returns: the y position
756 */
757 double
758 74 shumate_map_source_get_y (ShumateMapSource *map_source,
759 double zoom_level,
760 double latitude)
761 {
762 74 double sin_latitude;
763
764
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 74 times.
74 g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0.0);
765
766
1/2
✓ Branch 5 → 6 taken 74 times.
✗ Branch 5 → 7 not taken.
74 latitude = CLAMP (latitude, SHUMATE_MIN_LATITUDE, SHUMATE_MAX_LATITUDE);
767 /* FIXME: support other projections */
768 74 sin_latitude = sin (latitude * G_PI / 180.0);
769 74 return (0.5 - log ((1.0 + sin_latitude) / (1.0 - sin_latitude)) / (4.0 * G_PI)) * map_size (map_source, zoom_level);
770 }
771
772 /**
773 * shumate_map_source_get_longitude:
774 * @map_source: a #ShumateMapSource
775 * @zoom_level: the zoom level
776 * @x: a x position
777 *
778 * Gets the longitude corresponding to this x position in the map source's
779 * projection.
780 *
781 * Returns: the longitude
782 */
783 double
784 74 shumate_map_source_get_longitude (ShumateMapSource *map_source,
785 double zoom_level,
786 double x)
787 {
788 74 double longitude;
789
790
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 74 times.
74 g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0.0);
791
792 /* FIXME: support other projections */
793 74 longitude = x / map_size (map_source, zoom_level) * 360.0 - 180.0;
794
795
1/2
✓ Branch 6 → 7 taken 74 times.
✗ Branch 6 → 8 not taken.
74 return CLAMP (longitude, SHUMATE_MIN_LONGITUDE, SHUMATE_MAX_LONGITUDE);
796 }
797
798 /**
799 * shumate_map_source_get_latitude:
800 * @map_source: a #ShumateMapSource
801 * @zoom_level: the zoom level
802 * @y: a y position
803 *
804 * Gets the latitude corresponding to this y position in the map source's
805 * projection.
806 *
807 * Returns: the latitude
808 */
809 double
810 74 shumate_map_source_get_latitude (ShumateMapSource *map_source,
811 double zoom_level,
812 double y)
813 {
814 74 double latitude, dy;
815
816
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 74 times.
74 g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0.0);
817 /* FIXME: support other projections */
818 74 dy = 0.5 - y / map_size (map_source, zoom_level);
819 74 latitude = 90.0 - 360.0 / G_PI * atan (exp (-dy * 2.0 * G_PI));
820
821
1/2
✓ Branch 6 → 7 taken 74 times.
✗ Branch 6 → 8 not taken.
74 return CLAMP (latitude, SHUMATE_MIN_LATITUDE, SHUMATE_MAX_LATITUDE);
822 }
823
824 /**
825 * shumate_map_source_get_row_count:
826 * @map_source: a #ShumateMapSource
827 * @zoom_level: the zoom level
828 *
829 * Gets the number of tiles in a row at this zoom level for this map source.
830 *
831 * Returns: the number of tiles in a row
832 */
833 guint
834 ✗ shumate_map_source_get_row_count (ShumateMapSource *map_source,
835 guint zoom_level)
836 {
837 ✗ g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0);
838 /* FIXME: support other projections */
839 ✗ return (zoom_level != 0) ? 2 << (zoom_level - 1) : 1;
840 }
841
842 /**
843 * shumate_map_source_get_column_count:
844 * @map_source: a #ShumateMapSource
845 * @zoom_level: the zoom level
846 *
847 * Gets the number of tiles in a column at this zoom level for this map
848 * source.
849 *
850 * Returns: the number of tiles in a column
851 */
852 guint
853 296 shumate_map_source_get_column_count (ShumateMapSource *map_source,
854 guint zoom_level)
855 {
856
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 296 times.
296 g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0);
857 /* FIXME: support other projections */
858
2/2
✓ Branch 5 → 6 taken 280 times.
✓ Branch 5 → 7 taken 16 times.
296 return (zoom_level != 0) ? 2 << (zoom_level - 1) : 1;
859 }
860
861 #define EARTH_RADIUS 6378137.0 /* meters, Equatorial radius */
862
863 /**
864 * shumate_map_source_get_meters_per_pixel:
865 * @map_source: a #ShumateMapSource
866 * @zoom_level: the zoom level
867 * @latitude: a latitude
868 * @longitude: a longitude
869 *
870 * Gets meters per pixel at the position on the map using this map source's projection.
871 *
872 * Returns: the meters per pixel
873 */
874 double
875 ✗ shumate_map_source_get_meters_per_pixel (ShumateMapSource *map_source,
876 double zoom_level,
877 double latitude,
878 G_GNUC_UNUSED double longitude)
879 {
880 ✗ g_return_val_if_fail (SHUMATE_IS_MAP_SOURCE (map_source), 0.0);
881
882 /*
883 * Width is in pixels. (1 px)
884 * m/px = radius_at_latitude / width_in_pixels
885 * k = radius of earth = 6 378.1 km
886 * radius_at_latitude = 2pi * k * sin (pi/2-theta)
887 */
888
889 /* FIXME: support other projections */
890 ✗ return 2.0 * G_PI * EARTH_RADIUS * sin (G_PI / 2.0 - G_PI / 180.0 * latitude) / map_size (map_source, zoom_level);
891 }
892