• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MapServer / MapServer / 25799423251

13 May 2026 12:35PM UTC coverage: 41.802% (+0.001%) from 41.801%
25799423251

push

github

jmckenna
SECURITY.md: add note about automated scanners

motivation: avoid https://github.com/MapServer/MapServer/pull/7502

62990 of 150688 relevant lines covered (41.8%)

25378.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.46
/src/mapscale.c
1
/******************************************************************************
2
 * $Id$
3
 *
4
 * Project:  MapServer
5
 * Purpose:  Scale object rendering.
6
 * Author:   Steve Lime and the MapServer team.
7
 *
8
 ******************************************************************************
9
 * Copyright (c) 1996-2005 Regents of the University of Minnesota.
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a
12
 * copy of this software and associated documentation files (the "Software"),
13
 * to deal in the Software without restriction, including without limitation
14
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
 * and/or sell copies of the Software, and to permit persons to whom the
16
 * Software is furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies of this Software or works derived from this Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
 * DEALINGS IN THE SOFTWARE.
28
 ****************************************************************************/
29

30
#include "mapserver.h"
31

32
#define VMARGIN 3 /* buffer around the scalebar */
33
#define HMARGIN 3
34
#define VSPACING .8 /* spacing (% of font height) between scalebar and text */
35
#define VSLOP 5     /* makes things fit a bit better vertically */
36

37
/*
38
** Match this with with unit enumerations is mapserver.h
39
*/
40
static char *unitText[9] = {
41
    "in", "ft", "mi", "m", "km",
42
    "dd", "??", "??", "NM"}; /* MS_PIXEL and MS_PERCENTAGE not used */
43
double inchesPerUnit[9] = {1,       12, 63360.0, 39.3701,   39370.1,
44
                           4374754, 1,  1,       72913.3858};
45

46
static double roundInterval(double d) {
1,054✔
47
  if (d < .001)
1,054✔
48
    return (MS_NINT(d * 10000) / 10000.0);
×
49
  if (d < .01)
1,054✔
50
    return (MS_NINT(d * 1000) / 1000.0);
×
51
  if (d < .1)
1,054✔
52
    return (MS_NINT(d * 100) / 100.0);
×
53
  if (d < 1)
1,054✔
54
    return (MS_NINT(d * 10) / 10.0);
1,034✔
55
  if (d < 100)
20✔
56
    return (MS_NINT(d));
14✔
57
  if (d < 1000)
6✔
58
    return (MS_NINT(d / 10) * 10);
×
59
  if (d < 10000)
6✔
60
    return (MS_NINT(d / 100) * 100);
×
61
  if (d < 100000)
6✔
62
    return (MS_NINT(d / 1000) * 1000);
6✔
63
  if (d < 1000000)
×
64
    return (MS_NINT(d / 10000) * 10000);
×
65
  if (d < 10000000)
×
66
    return (MS_NINT(d / 100000) * 100000);
×
67
  if (d < 100000000)
×
68
    return (MS_NINT(d / 1000000) * 1000000);
×
69

70
  return (-1);
71
}
72

73
/*
74
** Calculate the approximate scale based on a few parameters. Note that this
75
*assumes the scale is
76
** the same in the x direction as in the y direction, so run msAdjustExtent(...)
77
*first.
78
*/
79
int msCalculateScale(rectObj extent, int units, int width, int height,
1,668✔
80
                     double resolution, double *scale) {
81
  double md, gd, center_y;
82

83
  /* if((extent.maxx == extent.minx) || (extent.maxy == extent.miny))   */
84
  if (!MS_VALID_EXTENT(extent)) {
1,668✔
85
    msSetError(MS_MISCERR,
×
86
               "Invalid image extent, minx=%lf, miny=%lf, maxx=%lf, maxy=%lf.",
87
               "msCalculateScale()", extent.minx, extent.miny, extent.maxx,
88
               extent.maxy);
89
    return (MS_FAILURE);
×
90
  }
91

92
  if ((width <= 0) || (height <= 0)) {
1,668✔
93
    msSetError(MS_MISCERR, "Invalid image width or height.",
3✔
94
               "msCalculateScale()");
95
    return (MS_FAILURE);
3✔
96
  }
97

98
  switch (units) {
1,665✔
99
  case (MS_DD):
1,665✔
100
  case (MS_METERS):
101
  case (MS_KILOMETERS):
102
  case (MS_MILES):
103
  case (MS_NAUTICALMILES):
104
  case (MS_INCHES):
105
  case (MS_FEET):
106
    center_y = (extent.miny + extent.maxy) / 2.0;
1,665✔
107
    md = (width - 1) /
3,330✔
108
         (resolution *
1,665✔
109
          msInchesPerUnit(
1,665✔
110
              units, center_y)); /* remember, we use a pixel-center to
111
                                    pixel-center extent, hence the width-1 */
112
    gd = extent.maxx - extent.minx;
1,665✔
113
    *scale = gd / md;
1,665✔
114
    break;
1,665✔
115
  default:
×
116
    *scale = -1; /* this is not an error */
×
117
    break;
×
118
  }
119

120
  return (MS_SUCCESS);
121
}
122

123
double msInchesPerUnit(int units, double center_lat) {
6,176✔
124
  (void)center_lat;
125
  double lat_adj = 1.0, ipu = 1.0;
126

127
  switch (units) {
6,176✔
128
  case (MS_METERS):
5,656✔
129
  case (MS_KILOMETERS):
130
  case (MS_MILES):
131
  case (MS_NAUTICALMILES):
132
  case (MS_INCHES):
133
  case (MS_FEET):
134
    ipu = inchesPerUnit[units];
5,656✔
135
    break;
5,656✔
136
  case (MS_DD):
520✔
137
    /* With geographical (DD) coordinates, we adjust the inchesPerUnit
138
     * based on the latitude of the center of the view. For this we assume
139
     * we have a perfect sphere and just use cos(lat) in our calculation.
140
     */
141
#ifdef ENABLE_VARIABLE_INCHES_PER_DEGREE
142
    if (center_lat != 0.0) {
143
      double cos_lat;
144
      cos_lat = cos(MS_PI * center_lat / 180.0);
145
      lat_adj = sqrt(1 + cos_lat * cos_lat) / sqrt(2.0);
146
    }
147
#endif
148
    ipu = inchesPerUnit[units] * lat_adj;
520✔
149
    break;
520✔
150
  default:
151
    break;
152
  }
153

154
  return ipu;
6,176✔
155
}
156

157
#define X_STEP_SIZE 5
158

159
imageObj *msDrawScalebar(mapObj *map) {
167✔
160
  int status;
161
  char label[32];
162
  double i, msx;
163
  int j;
164
  int isx, sx, sy, ox, oy, state, dsx;
165
  pointObj p;
166
  rectObj r;
167
  imageObj *image = NULL;
168
  double fontWidth, fontHeight;
169
  outputFormatObj *format = NULL;
167✔
170
  strokeStyleObj strokeStyle = {0};
167✔
171
  shapeObj shape;
172
  lineObj line;
173
  pointObj points[5];
174
  textSymbolObj ts;
175
  rendererVTableObj *renderer;
176

177
  strokeStyle.patternlength = 0;
178
  initTextSymbol(&ts);
167✔
179

180
  if ((int)map->units == -1) {
167✔
181
    msSetError(MS_MISCERR, "Map units not set.", "msDrawScalebar()");
×
182
    return (NULL);
×
183
  }
184

185
  renderer = MS_MAP_RENDERER(map);
167✔
186
  if (!renderer || !MS_MAP_RENDERER(map)->supports_pixel_buffer) {
167✔
187
    msSetError(MS_MISCERR, "Outputformat not supported for scalebar",
×
188
               "msDrawScalebar()");
189
    return (NULL);
×
190
  }
191

192
  msPopulateTextSymbolForLabelAndString(
167✔
193
      &ts, &map->scalebar.label, msStrdup("0123456789"), 1.0,
194
      map->resolution / map->defresolution, 0);
167✔
195

196
  /*
197
   *  A string containing the ten decimal digits is rendered to compute an
198
   * average cell size for each number, which is used later to place labels on
199
   * the scalebar.
200
   */
201

202
  if (msGetTextSymbolSize(map, &ts, &r) != MS_SUCCESS) {
167✔
203
    return NULL;
204
  }
205
  fontWidth = (r.maxx - r.minx) / 10.0;
167✔
206
  fontHeight = r.maxy - r.miny;
167✔
207

208
  map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height);
167✔
209
  status = msCalculateScale(map->extent, map->units, map->width, map->height,
167✔
210
                            map->resolution, &map->scaledenom);
211
  if (status != MS_SUCCESS) {
167✔
212
    return (NULL);
213
  }
214
  dsx = map->scalebar.width - 2 * HMARGIN;
167✔
215
  do {
216
    msx = (map->cellsize * dsx) / (msInchesPerUnit(map->scalebar.units, 0) /
1,054✔
217
                                   msInchesPerUnit(map->units, 0));
1,054✔
218
    i = roundInterval(msx / map->scalebar.intervals);
1,054✔
219
    snprintf(label, sizeof(label), "%g",
1,054✔
220
             map->scalebar.intervals * i); /* last label */
221
    isx = MS_NINT((i / (msInchesPerUnit(map->units, 0) /
1,054✔
222
                        msInchesPerUnit(map->scalebar.units, 0))) /
223
                  map->cellsize);
224
    sx = (map->scalebar.intervals * isx) +
1,054✔
225
         MS_NINT((1.5 + strlen(label) / 2.0 +
1,054✔
226
                  strlen(unitText[map->scalebar.units])) *
227
                 fontWidth);
228

229
    if (sx <= (map->scalebar.width - 2 * HMARGIN))
1,054✔
230
      break; /* it will fit */
231

232
    dsx -= X_STEP_SIZE; /* change the desired size in hopes that it will fit in
887✔
233
                           user supplied width */
234
  } while (1);
235

236
  sy = (2 * VMARGIN) + MS_NINT(VSPACING * fontHeight) + fontHeight +
167✔
237
       map->scalebar.height - VSLOP;
167✔
238

239
  /*Ensure we have an image format representing the options for the scalebar.*/
240
  msApplyOutputFormat(&format, map->outputformat, map->scalebar.transparent);
167✔
241

242
  if (map->scalebar.transparent == MS_OFF) {
167✔
243
    if (!MS_VALID_COLOR(map->scalebar.imagecolor))
6✔
244
      MS_INIT_COLOR(map->scalebar.imagecolor, 255, 255, 255, 255);
6✔
245
  }
246
  image = msImageCreate(map->scalebar.width, sy, format, map->web.imagepath,
167✔
247
                        map->web.imageurl, map->resolution, map->defresolution,
248
                        &map->scalebar.imagecolor);
249

250
  /* did we succeed in creating the image? */
251
  if (!image) {
167✔
252
    msSetError(MS_MISCERR, "Unable to initialize image.", "msDrawScalebar()");
×
253
    return NULL;
×
254
  }
255
  image->map = map;
167✔
256

257
  /* drop this reference to output format */
258
  msApplyOutputFormat(&format, NULL, MS_NOOVERRIDE);
167✔
259

260
  switch (map->scalebar.align) {
167✔
261
  case (MS_ALIGN_LEFT):
262
    ox = HMARGIN;
263
    break;
264
  case (MS_ALIGN_RIGHT):
×
265
    ox = MS_NINT((map->scalebar.width - sx) + fontWidth);
×
266
    break;
×
267
  default:
167✔
268
    ox = MS_NINT((map->scalebar.width - sx) / 2.0 +
167✔
269
                 fontWidth / 2.0); /* center the computed scalebar */
270
  }
271
  oy = VMARGIN;
272

273
  switch (map->scalebar.style) {
167✔
274
  case (0): {
167✔
275

276
    line.numpoints = 5;
167✔
277
    line.point = points;
167✔
278
    shape.line = &line;
167✔
279
    shape.numlines = 1;
167✔
280
    if (MS_VALID_COLOR(map->scalebar.color)) {
167✔
281
      INIT_STROKE_STYLE(strokeStyle);
167✔
282
      strokeStyle.color = &map->scalebar.outlinecolor;
167✔
283
      strokeStyle.color->alpha = 255;
167✔
284
      strokeStyle.width = 1;
167✔
285
    }
286
    map->scalebar.backgroundcolor.alpha = 255;
167✔
287
    map->scalebar.color.alpha = 255;
167✔
288
    state = 1; /* 1 means filled */
289
    for (j = 0; j < map->scalebar.intervals; j++) {
825✔
290
      points[0].x = points[4].x = points[3].x = ox + j * isx + 0.5;
658✔
291
      points[0].y = points[4].y = points[1].y = oy + 0.5;
658✔
292
      points[1].x = points[2].x = ox + (j + 1) * isx + 0.5;
658✔
293
      points[2].y = points[3].y = oy + map->scalebar.height + 0.5;
658✔
294
      if (state == 1 && MS_VALID_COLOR(map->scalebar.color))
658✔
295
        status = renderer->renderPolygon(image, &shape, &map->scalebar.color);
334✔
296
      else if (MS_VALID_COLOR(map->scalebar.backgroundcolor))
324✔
297
        status = renderer->renderPolygon(image, &shape,
320✔
298
                                         &map->scalebar.backgroundcolor);
299

300
      if (MS_UNLIKELY(status == MS_FAILURE)) {
658✔
301
        goto scale_cleanup;
×
302
      }
303

304
      if (strokeStyle.color) {
658✔
305
        status = renderer->renderLine(image, &shape, &strokeStyle);
658✔
306

307
        if (MS_UNLIKELY(status == MS_FAILURE)) {
658✔
308
          goto scale_cleanup;
×
309
        }
310
      }
311

312
      snprintf(label, sizeof(label), "%g", j * i);
658✔
313
      map->scalebar.label.position = MS_CC;
658✔
314
      p.x = ox + j * isx; /* + MS_NINT(fontPtr->w/2); */
658✔
315
      p.y = oy + map->scalebar.height + MS_NINT(VSPACING * fontHeight);
658✔
316
      status = msDrawLabel(map, image, p, msStrdup(label), &map->scalebar.label,
658✔
317
                           1.0);
318
      if (MS_UNLIKELY(status == MS_FAILURE)) {
658✔
319
        goto scale_cleanup;
×
320
      }
321
      state = -state;
658✔
322
    }
323
    snprintf(label, sizeof(label), "%g", j * i);
167✔
324
    ox = ox + j * isx - MS_NINT((strlen(label) * fontWidth) / 2.0);
167✔
325
    snprintf(label, sizeof(label), "%g %s", j * i,
167✔
326
             unitText[map->scalebar.units]);
167✔
327
    map->scalebar.label.position = MS_CR;
167✔
328
    p.x = ox; /* + MS_NINT(fontPtr->w/2); */
167✔
329
    p.y = oy + map->scalebar.height + MS_NINT(VSPACING * fontHeight);
167✔
330
    status =
331
        msDrawLabel(map, image, p, msStrdup(label), &map->scalebar.label, 1.0);
167✔
332
    if (MS_UNLIKELY(status == MS_FAILURE)) {
167✔
333
      goto scale_cleanup;
×
334
    }
335
    break;
336
  }
337
  case (1): {
×
338
    line.numpoints = 2;
×
339
    line.point = points;
×
340
    shape.line = &line;
×
341
    shape.numlines = 1;
×
342
    if (MS_VALID_COLOR(map->scalebar.color)) {
×
343
      strokeStyle.width = 1;
×
344
      strokeStyle.color = &map->scalebar.color;
×
345
    }
346

347
    points[0].y = points[1].y = oy;
×
348
    points[0].x = ox;
×
349
    points[1].x = ox + isx * map->scalebar.intervals;
×
350
    status = renderer->renderLine(image, &shape, &strokeStyle);
×
351
    if (MS_UNLIKELY(status == MS_FAILURE)) {
×
352
      goto scale_cleanup;
×
353
    }
354

355
    points[0].y = oy;
×
356
    points[1].y = oy + map->scalebar.height;
×
357
    p.y = oy + map->scalebar.height + MS_NINT(VSPACING * fontHeight);
×
358
    for (j = 0; j <= map->scalebar.intervals; j++) {
×
359
      points[0].x = points[1].x = ox + j * isx;
×
360
      status = renderer->renderLine(image, &shape, &strokeStyle);
×
361
      if (MS_UNLIKELY(status == MS_FAILURE)) {
×
362
        goto scale_cleanup;
×
363
      }
364

365
      snprintf(label, sizeof(label), "%g", j * i);
×
366
      if (j != map->scalebar.intervals) {
×
367
        map->scalebar.label.position = MS_CC;
×
368
        p.x = ox + j * isx; /* + MS_NINT(fontPtr->w/2); */
×
369
      } else {
370
        snprintf(label, sizeof(label), "%g %s", j * i,
×
371
                 unitText[map->scalebar.units]);
×
372
        map->scalebar.label.position = MS_CR;
×
373
        p.x = ox + j * isx - MS_NINT((strlen(label) * fontWidth) / 2.0);
×
374
      }
375
      status = msDrawLabel(map, image, p, msStrdup(label), &map->scalebar.label,
×
376
                           1.0);
377
      if (MS_UNLIKELY(status == MS_FAILURE)) {
×
378
        goto scale_cleanup;
×
379
      }
380
    }
381
    break;
382
  }
383
  default:
×
384
    msSetError(MS_MISCERR, "Unsupported scalebar style.", "msDrawScalebar()");
×
385
    return (NULL);
×
386
  }
387

388
scale_cleanup:
167✔
389
  freeTextSymbol(&ts);
167✔
390
  if (MS_UNLIKELY(status == MS_FAILURE)) {
167✔
391
    msFreeImage(image);
×
392
    return NULL;
×
393
  }
394
  return (image);
395
}
396

397
int msEmbedScalebar(mapObj *map, imageObj *img) {
167✔
398
  int l, index, s, status = MS_SUCCESS;
399
  pointObj point;
400
  imageObj *image = NULL;
401
  rendererVTableObj *renderer;
402
  symbolObj *embeddedSymbol;
403
  char *imageType = NULL;
404

405
  index = msGetSymbolIndex(&(map->symbolset), "scalebar", MS_FALSE);
167✔
406
  if (index != -1)
167✔
407
    msRemoveSymbol(&(map->symbolset),
1✔
408
                   index); /* remove cached symbol in case the function is
409
   called multiple times with different zoom levels */
410

411
  if ((embeddedSymbol = msGrowSymbolSet(&map->symbolset)) == NULL)
167✔
412
    return MS_FAILURE;
413

414
  s = map->symbolset.numsymbols;
167✔
415
  map->symbolset.numsymbols++;
167✔
416

417
  if (!MS_RENDERER_PLUGIN(map->outputformat) ||
167✔
418
      !MS_MAP_RENDERER(map)->supports_pixel_buffer) {
167✔
419
    imageType = msStrdup(map->imagetype); /* save format */
×
420
    if MS_DRIVER_CAIRO (map->outputformat)
×
421
      map->outputformat = msSelectOutputFormat(map, "cairopng");
×
422
    else
423
      map->outputformat = msSelectOutputFormat(map, "png");
×
424

425
    msInitializeRendererVTable(map->outputformat);
×
426
  }
427
  renderer = MS_MAP_RENDERER(map);
167✔
428

429
  image = msDrawScalebar(map);
167✔
430

431
  if (imageType) {
167✔
432
    map->outputformat =
×
433
        msSelectOutputFormat(map, imageType); /* restore format */
×
434
    msFree(imageType);
×
435
  }
436

437
  if (!image) {
167✔
438
    return MS_FAILURE;
439
  }
440
  embeddedSymbol->pixmap_buffer = calloc(1, sizeof(rasterBufferObj));
167✔
441
  MS_CHECK_ALLOC(embeddedSymbol->pixmap_buffer, sizeof(rasterBufferObj),
167✔
442
                 MS_FAILURE);
443

444
  if (MS_SUCCESS !=
167✔
445
      renderer->getRasterBufferCopy(image, embeddedSymbol->pixmap_buffer)) {
167✔
446
    return MS_FAILURE;
447
  }
448

449
  embeddedSymbol->type = MS_SYMBOL_PIXMAP; /* initialize a few things */
167✔
450
  embeddedSymbol->name = msStrdup("scalebar");
167✔
451
  embeddedSymbol->sizex = embeddedSymbol->pixmap_buffer->width;
167✔
452
  embeddedSymbol->sizey = embeddedSymbol->pixmap_buffer->height;
167✔
453
  if (map->scalebar.transparent) {
167✔
454
    embeddedSymbol->transparent = MS_TRUE;
161✔
455
    embeddedSymbol->transparentcolor = 0;
161✔
456
  }
457

458
  switch (map->scalebar.position) {
167✔
459
  case (MS_LL):
12✔
460
    point.x = MS_NINT(embeddedSymbol->pixmap_buffer->width / 2.0) +
12✔
461
              map->scalebar.offsetx;
12✔
462
    point.y = map->height -
12✔
463
              MS_NINT(embeddedSymbol->pixmap_buffer->height / 2.0) -
12✔
464
              map->scalebar.offsety;
12✔
465
    break;
12✔
466
  case (MS_LR):
155✔
467
    point.x = map->width - MS_NINT(embeddedSymbol->pixmap_buffer->width / 2.0) -
155✔
468
              map->scalebar.offsetx;
155✔
469
    point.y = map->height -
155✔
470
              MS_NINT(embeddedSymbol->pixmap_buffer->height / 2.0) -
155✔
471
              map->scalebar.offsety;
155✔
472
    break;
155✔
473
  case (MS_LC):
×
474
    point.x = MS_NINT(map->width / 2.0) + map->scalebar.offsetx;
×
475
    point.y = map->height -
×
476
              MS_NINT(embeddedSymbol->pixmap_buffer->height / 2.0) -
×
477
              map->scalebar.offsety;
×
478
    break;
×
479
  case (MS_UR):
×
480
    point.x = map->width - MS_NINT(embeddedSymbol->pixmap_buffer->width / 2.0) -
×
481
              map->scalebar.offsetx;
×
482
    point.y = MS_NINT(embeddedSymbol->pixmap_buffer->height / 2.0) +
×
483
              map->scalebar.offsety;
×
484
    break;
×
485
  case (MS_UL):
×
486
    point.x = MS_NINT(embeddedSymbol->pixmap_buffer->width / 2.0) +
×
487
              map->scalebar.offsetx;
×
488
    point.y = MS_NINT(embeddedSymbol->pixmap_buffer->height / 2.0) +
×
489
              map->scalebar.offsety;
×
490
    break;
×
491
  case (MS_UC):
×
492
    point.x = MS_NINT(map->width / 2.0) + map->scalebar.offsetx;
×
493
    point.y = MS_NINT(embeddedSymbol->pixmap_buffer->height / 2.0) +
×
494
              map->scalebar.offsety;
×
495
    break;
×
496
  }
497

498
  l = msGetLayerIndex(map, "__embed__scalebar");
167✔
499
  if (l == -1) {
167✔
500
    if (msGrowMapLayers(map) == NULL)
166✔
501
      return (-1);
502
    l = map->numlayers;
166✔
503
    map->numlayers++;
166✔
504
    if (initLayer((GET_LAYER(map, l)), map) == -1)
166✔
505
      return (-1);
506
    GET_LAYER(map, l)->name = msStrdup("__embed__scalebar");
166✔
507
    GET_LAYER(map, l)->type = MS_LAYER_POINT;
166✔
508

509
    if (msGrowLayerClasses(GET_LAYER(map, l)) == NULL)
166✔
510
      return (-1);
511

512
    if (initClass(GET_LAYER(map, l)->class[0]) == -1)
166✔
513
      return (-1);
514
    GET_LAYER(map, l)->numclasses = 1; /* so we make sure to free it */
166✔
515

516
    /* update the layer order list with the layer's index. */
517
    map->layerorder[l] = l;
166✔
518
  }
519

520
  GET_LAYER(map, l)->status = MS_ON;
167✔
521
  if (map->scalebar.postlabelcache) { /* add it directly to the image */
167✔
522
    if (msMaybeAllocateClassStyle(GET_LAYER(map, l)->class[0], 0) == MS_FAILURE)
155✔
523
      return MS_FAILURE;
524
    GET_LAYER(map, l)->class[0]->styles[0]->symbol = s;
155✔
525
    status = msDrawMarkerSymbol(map, img, &point,
155✔
526
                                GET_LAYER(map, l)->class[0] -> styles[0], 1.0);
527
    if (MS_UNLIKELY(status == MS_FAILURE)) {
155✔
528
      goto embed_cleanup;
×
529
    }
530
  } else {
531
    if (!GET_LAYER(map, l)->class[0] -> labels) {
12✔
532
      if (msGrowClassLabels(GET_LAYER(map, l)->class[0]) == NULL)
12✔
533
        return MS_FAILURE;
534
      initLabel(GET_LAYER(map, l)->class[0] -> labels[0]);
12✔
535
      GET_LAYER(map, l)->class[0]->numlabels = 1;
12✔
536
      GET_LAYER(map, l)->class[0]->labels[0]->force = MS_TRUE;
12✔
537
      GET_LAYER(map, l)->class[0]->labels[0]->size =
12✔
538
          MS_MEDIUM; /* must set a size to have a valid label definition */
539
      GET_LAYER(map, l)->class[0]->labels[0]->priority = MS_MAX_LABEL_PRIORITY;
12✔
540
    }
541
    if (GET_LAYER(map, l)->class[0] -> labels[0] -> numstyles == 0) {
12✔
542
      if (msGrowLabelStyles(GET_LAYER(map, l)->class[0] -> labels[0]) == NULL)
12✔
543
        return (MS_FAILURE);
544
      GET_LAYER(map, l)->class[0]->labels[0]->numstyles = 1;
12✔
545
      initStyle(GET_LAYER(map, l)->class[0] -> labels[0] -> styles[0]);
12✔
546
      GET_LAYER(map, l)->class[0]->labels[0]->styles[0]->_geomtransform.type =
12✔
547
          MS_GEOMTRANSFORM_LABELPOINT;
548
    }
549
    GET_LAYER(map, l)->class[0]->labels[0]->styles[0]->symbol = s;
12✔
550
    status = msAddLabel(map, img, GET_LAYER(map, l)->class[0] -> labels[0], l,
12✔
551
                        0, NULL, &point, -1, NULL);
552
    if (MS_UNLIKELY(status == MS_FAILURE)) {
12✔
553
      goto embed_cleanup;
×
554
    }
555
  }
556

557
embed_cleanup:
12✔
558
  /* Mark layer as deleted so that it doesn't interfere with html legends or
559
   * with saving maps */
560
  GET_LAYER(map, l)->status = MS_DELETE;
167✔
561

562
  msFreeImage(image);
167✔
563
  return status;
167✔
564
}
565

566
/************************************************************************/
567
/* These two functions are used in PHP/Mapscript and Swig/Mapscript     */
568
/************************************************************************/
569

570
/************************************************************************/
571
/*  double GetDeltaExtentsUsingScale(double scale, int units,           */
572
/*                                   double centerLat, int width,       */
573
/*                                   double resolution)                 */
574
/*                                                                      */
575
/*      Utility function to return the maximum extent using the         */
576
/*      scale and the width of the image.                               */
577
/*                                                                      */
578
/*      Base on the function msCalculateScale (mapscale.c)              */
579
/************************************************************************/
580
double GetDeltaExtentsUsingScale(double scale, int units, double centerLat,
8✔
581
                                 int width, double resolution) {
582
  double md = 0.0;
583
  double dfDelta = -1.0;
584

585
  if (scale <= 0 || width <= 0)
8✔
586
    return -1;
587

588
  switch (units) {
8✔
589
  case (MS_DD):
8✔
590
  case (MS_METERS):
591
  case (MS_KILOMETERS):
592
  case (MS_MILES):
593
  case (MS_NAUTICALMILES):
594
  case (MS_INCHES):
595
  case (MS_FEET):
596
    /* remember, we use a pixel-center to pixel-center extent, hence the width-1
597
     */
598
    md = (width - 1) / (resolution * msInchesPerUnit(units, centerLat));
8✔
599
    dfDelta = md * scale;
8✔
600
    break;
8✔
601

602
  default:
603
    break;
604
  }
605

606
  return dfDelta;
607
}
608

609
/************************************************************************/
610
/*    static double Pix2Georef(int nPixPos, int nPixMin, double nPixMax,*/
611
/*                              double dfGeoMin, double dfGeoMax,       */
612
/*                              bool bULisYOrig)                        */
613
/*                                                                      */
614
/*      Utility function to convert a pixel pos to georef pos. If       */
615
/*      bULisYOrig parameter is set to true then the upper left is      */
616
/*      considered to be the Y origin.                                  */
617
/*                                                                      */
618
/************************************************************************/
619
double Pix2Georef(int nPixPos, int nPixMin, int nPixMax, double dfGeoMin,
8,974✔
620
                  double dfGeoMax, int bULisYOrig) {
621
  double dfPosGeo = 0.0;
622

623
  const double dfWidthGeo = dfGeoMax - dfGeoMin;
8,974✔
624
  const int nWidthPix = nPixMax - nPixMin;
8,974✔
625

626
  if (dfWidthGeo > 0.0 && nWidthPix > 0) {
8,974✔
627
    const double dfPixToGeo = dfWidthGeo / (double)nWidthPix;
8,974✔
628

629
    int nDeltaPix;
630
    if (!bULisYOrig)
8,974✔
631
      nDeltaPix = nPixPos - nPixMin;
4,487✔
632
    else
633
      nDeltaPix = nPixMax - nPixPos;
4,487✔
634

635
    const double dfDeltaGeo = nDeltaPix * dfPixToGeo;
8,974✔
636

637
    dfPosGeo = dfGeoMin + dfDeltaGeo;
8,974✔
638
  }
639
  return (dfPosGeo);
8,974✔
640
}
641

642
/* This function converts a pixel value in geo ref. The return value is in
643
 * layer units. This function has been added for the purpose of the ticket #1340
644
 */
645

646
double Pix2LayerGeoref(mapObj *map, layerObj *layer, int value) {
×
647
  double cellsize =
648
      MS_MAX(MS_CELLSIZE(map->extent.minx, map->extent.maxx, map->width),
×
649
             MS_CELLSIZE(map->extent.miny, map->extent.maxy, map->height));
650

651
  double resolutionFactor = map->resolution / map->defresolution;
×
652
  double unitsFactor = 1;
653

654
  if (layer->sizeunits != MS_PIXELS)
×
655
    unitsFactor =
×
656
        msInchesPerUnit(map->units, 0) / msInchesPerUnit(layer->sizeunits, 0);
×
657

658
  return value * cellsize * resolutionFactor * unitsFactor;
×
659
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc