1 /******************************************************************************
2 * $Id$
3 *
4 * Project: MapServer
5 * Purpose: Implements imagemap outputformat support.
6 * Author: Attila Csipa
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 #include "dxfcolor.h"
32
33 #include <stdarg.h>
34 #include <time.h>
35
36 #ifdef _WIN32
37 #include <fcntl.h>
38 #include <io.h>
39 #endif
40
41
42
43 #define MYDEBUG 0
44 #define DEBUG_IF if (MYDEBUG > 2)
45
46 /*
47 * Client-side imagemap support was originally written by
48 * Attila Csipa (http://prometheus.org.yu/me.php). C. Scott Ananian
49 * (http://cscott.net) cleaned up the code somewhat and made it more flexible:
50 * you can now customize the generated HREFs and create mouseover and
51 * mouseout attributes.
52 *
53 * Use
54 * IMAGETYPE imagemap
55 * to select this driver.
56 *
57 * The following FORMATOPTIONs are available. If any are set to the empty
58 * string the associated attribute will be suppressed.
59 * POLYHREF the href string to use for the <area> elements.
60 * use a %s to interpolate the area title.
61 * default: "javascript:Clicked('%s');"
62 * POLYMOUSEOVER the onMouseOver string to use for the <area> elements.
63 * use a %s to interpolate the area title.
64 * default: "" (ie the attribute is suppressed)
65 * POLYMOUSEOUT the onMouseOut string to use for the <area> elements.
66 * use a %s to interpolate the area title.
67 * default: "" (ie the attribute is suppressed)
68 * SYMBOLMOUSEOVER and SYMBOLMOUSEOUT are equivalent properties for
69 * <area> tags representing symbols, with the same defaults.
70 * MAPNAME the string which will be used in the name attribute
71 * of the <map> tag. There is no %s interpolation.
72 * default: "map1"
73 * SUPPRESS if "yes", then we will suppress area declarations with
74 * no title.
75 * default: "NO"
76 *
77 * For example, http://vevo.verifiedvoting.org/verifier contains this
78 * .map file fragment:
79 * OUTPUTFORMAT
80 * NAME imagemap
81 * DRIVER imagemap
82 * FORMATOPTION "POLYHREF=/verifier/map.php?state=%s"
83 * FORMATOPTION "SYMBOLHREF=#"
84 * FORMATOPTION "SUPPRESS=YES"
85 * FORMATOPTION "MAPNAME=map-48"
86 * FORMATOPTION "POLYMOUSEOUT=return nd();"
87 * FORMATOPTION "POLYMOUSEOVER=return overlib('%s');"
88 * END
89 */
90
91 /*-------------------------------------------------------------------------*/
92
93 /* A pString is a variable-length (appendable) string, stored as a triple:
94 * character pointer, allocated length, and used length. The one wrinkle
95 * is that we use pointers to the allocated size and character pointer,
96 * in order to support refering to fields declared elsewhere (ie in the
97 * 'image' data structure) for these. The 'iprintf' function appends
98 * to a pString. */
99 typedef struct pString {
100 /* these two fields are somewhere else */
101 char **string;
102 int *alloc_size;
103 /* this field is stored locally. */
104 int string_len;
105 } pString;
106 /* These are the pStrings we declare statically. One is the 'output'
107 * imagemap/dxf file; parts of this live in another data structure and
108 * are only referenced indirectly here. The other contains layer-specific
109 * information for the dxf output. */
110 static char *layerlist=NULL;
111 static int layersize=0;
112 static pString imgStr, layerStr= { &layerlist, &layersize, 0 };
113
114 /* Format strings for the various bits of a client-side imagemap. */
115 static const char *polyHrefFmt, *polyMOverFmt, *polyMOutFmt;
116 static const char *symbolHrefFmt, *symbolMOverFmt, *symbolMOutFmt;
117 static const char *mapName;
118 /* Should we suppress AREA declarations in imagemaps with no title? */
119 static int suppressEmpty=0;
120
121 /* Prevent buffer-overrun and format-string attacks by "sanitizing" any
122 * provided format string to fit the number of expected string arguments
123 * (MAX) exactly. */
makeFmtSafe(const char * fmt,int MAX)124 static const char *makeFmtSafe(const char *fmt, int MAX)
125 {
126 /* format string should have exactly 'MAX' %s */
127
128 char *result = msSmallMalloc(strlen(fmt)+1+3*MAX), *cp;
129 int numstr=0, saw_percent=0;
130
131 strcpy(result, fmt);
132 for (cp=result; *cp; cp++) {
133 if (saw_percent) {
134 if (*cp=='%') {
135 /* safe */
136 } else if (*cp=='s' && numstr<MAX) {
137 numstr++; /* still safe */
138 } else {
139 /* disable this unsafe format string! */
140 *(cp-1)=' ';
141 }
142 saw_percent=0;
143 } else if (*cp=='%')
144 saw_percent=1;
145 }
146 /* fixup format strings without enough %s in them */
147 while (numstr<MAX) {
148 strcpy(cp, "%.s"); /* print using zero-length precision */
149 cp+=3;
150 numstr++;
151 }
152 return result;
153 }
154
155 /* Append the given printf-style formatted string to the pString 'ps'.
156 * This is much cleaner (and faster) than the technique this file
157 * used to use! */
im_iprintf(pString * ps,const char * fmt,...)158 static void im_iprintf(pString *ps, const char *fmt, ...)
159 {
160 int n, remaining;
161 va_list ap;
162 do {
163 remaining = *(ps->alloc_size) - ps->string_len;
164 va_start(ap, fmt);
165 #if defined(HAVE_VSNPRINTF)
166 n = vsnprintf((*(ps->string)) + ps->string_len,
167 remaining, fmt, ap);
168 #else
169 /* If vsnprintf() is not available then require a minimum
170 * of 512 bytes of free space to prevent a buffer overflow
171 * This is not fully bulletproof but should help, see bug 1613
172 */
173 if (remaining < 512)
174 n = -1;
175 else
176 n = vsprintf((*(ps->string)) + ps->string_len, fmt, ap);
177 #endif
178 va_end(ap);
179 /* if that worked, we're done! */
180 if (-1<n && n<remaining) {
181 ps->string_len += n;
182 return;
183 } else { /* double allocated string size */
184 *(ps->alloc_size) *= 2;/* these keeps realloc linear.*/
185 if (*(ps->alloc_size) < 1024)
186 /* careful: initial size can be 0 */
187 *(ps->alloc_size)=1024;
188 if (n>-1 && *(ps->alloc_size) <= (n + ps->string_len))
189 /* ensure at least as much as what is needed */
190 *(ps->alloc_size) = n+ps->string_len+1;
191 *(ps->string) = (char *) msSmallRealloc
192 (*(ps->string), *(ps->alloc_size));
193 /* if realloc doesn't work, we're screwed! */
194 }
195 } while (1); /* go back and try again. */
196 }
197
198
199
200 static int lastcolor=-1;
matchdxfcolor(colorObj col)201 static int matchdxfcolor(colorObj col)
202 {
203 int best=7;
204 int delta=128*255;
205 int tcolor = 0;
206 if (lastcolor != -1)
207 return lastcolor;
208 while (tcolor < 256 && (ctable[tcolor].r != col.red || ctable[tcolor].g != col.green || ctable[tcolor].b != col.blue)) {
209 if (abs(
210 (ctable[tcolor].r - col.red) * (ctable[tcolor].r - col.red)+
211 (ctable[tcolor].b - col.blue) * (ctable[tcolor].b - col.blue) +
212 (ctable[tcolor].g - col.green) * (ctable[tcolor].g - col.green) < delta)
213 ) {
214 best = tcolor;
215 delta = abs(
216 (ctable[tcolor].r - col.red) * (ctable[tcolor].r - col.red)+
217 (ctable[tcolor].b - col.blue) * (ctable[tcolor].b - col.blue) +
218 (ctable[tcolor].g - col.green) * (ctable[tcolor].g - col.green)
219 );
220 }
221 tcolor++;
222 }
223 if (tcolor >= 256) tcolor = best;
224 /* DEBUG_IF printf("%d/%d/%d (%d/%d - %d), %d : %d/%d/%d<BR>\n", ctable[tcolor].r, ctable[tcolor].g, ctable[tcolor].b, tcolor, best, delta, lastcolor, col.red, col.green, col.blue); */
225 lastcolor = tcolor;
226 return tcolor;
227 }
228
229 static char* lname;
230 static int dxf;
231
msImageStartLayerIM(mapObj * map,layerObj * layer,imageObj * image)232 void msImageStartLayerIM(mapObj *map, layerObj *layer, imageObj *image)
233 {
234 DEBUG_IF printf("ImageStartLayerIM\n<BR>");
235 free(lname);
236 if (layer->name)
237 lname = msStrdup(layer->name);
238 else
239 lname = msStrdup("NONE");
240 if (dxf == 2) {
241 im_iprintf(&layerStr, "LAYER\n%s\n", lname);
242 } else if (dxf) {
243 im_iprintf(&layerStr,
244 " 0\nLAYER\n 2\n%s\n"
245 " 70\n 64\n 6\nCONTINUOUS\n", lname);
246 }
247 lastcolor = -1;
248 }
249
250 /*
251 * Utility function to create a IM image. Returns
252 * a pointer to an imageObj structure.
253 */
msImageCreateIM(int width,int height,outputFormatObj * format,char * imagepath,char * imageurl,double resolution,double defresolution)254 imageObj *msImageCreateIM(int width, int height, outputFormatObj *format,
255 char *imagepath, char *imageurl, double resolution, double defresolution)
256 {
257 imageObj *image=NULL;
258 if (setvbuf(stdout, NULL, _IONBF , 0)) {
259 printf("Whoops...");
260 };
261 DEBUG_IF printf("msImageCreateIM<BR>\n");
262 if (width > 0 && height > 0) {
263 image = (imageObj *)msSmallCalloc(1,sizeof(imageObj));
264 imgStr.string = &(image->img.imagemap);
265 imgStr.alloc_size = &(image->size);
266
267 image->format = format;
268 format->refcount++;
269
270 image->width = width;
271 image->height = height;
272 image->imagepath = NULL;
273 image->imageurl = NULL;
274 image->resolution = resolution;
275 image->resolutionfactor = resolution/defresolution;
276
277 if( strcasecmp("ON",msGetOutputFormatOption( format, "DXF", "OFF" )) == 0) {
278 dxf = 1;
279 im_iprintf(&layerStr, " 2\nLAYER\n 70\n 10\n");
280 } else
281 dxf = 0;
282
283 if( strcasecmp("ON",msGetOutputFormatOption( format, "SCRIPT", "OFF" )) == 0) {
284 dxf = 2;
285 im_iprintf(&layerStr, "");
286 }
287
288 /* get href formation string options */
289 polyHrefFmt = makeFmtSafe(msGetOutputFormatOption
290 ( format, "POLYHREF", "javascript:Clicked('%s');"), 1);
291 polyMOverFmt = makeFmtSafe(msGetOutputFormatOption
292 ( format, "POLYMOUSEOVER", ""), 1);
293 polyMOutFmt = makeFmtSafe(msGetOutputFormatOption
294 ( format, "POLYMOUSEOUT", ""), 1);
295 symbolHrefFmt = makeFmtSafe(msGetOutputFormatOption
296 ( format, "SYMBOLHREF", "javascript:SymbolClicked();"), 1);
297 symbolMOverFmt = makeFmtSafe(msGetOutputFormatOption
298 ( format, "SYMBOLMOUSEOVER", ""), 1);
299 symbolMOutFmt = makeFmtSafe(msGetOutputFormatOption
300 ( format, "SYMBOLMOUSEOUT", ""), 1);
301 /* get name of client-side image map */
302 mapName = msGetOutputFormatOption
303 ( format, "MAPNAME", "map1" );
304 /* should we suppress area declarations with no title? */
305 if( strcasecmp("YES",msGetOutputFormatOption( format, "SUPPRESS", "NO" )) == 0) {
306 suppressEmpty=1;
307 }
308
309 lname = msStrdup("NONE");
310 *(imgStr.string) = msStrdup("");
311 if (*(imgStr.string)) {
312 *(imgStr.alloc_size) =
313 imgStr.string_len = strlen(*(imgStr.string));
314 } else {
315 *(imgStr.alloc_size) =
316 imgStr.string_len = 0;
317 }
318 if (imagepath) {
319 image->imagepath = msStrdup(imagepath);
320 }
321 if (imageurl) {
322 image->imageurl = msStrdup(imageurl);
323 }
324
325 return image;
326 } else {
327 msSetError(MS_IMGERR,
328 "Cannot create IM image of size %d x %d.",
329 "msImageCreateIM()", width, height );
330 }
331 return image;
332 }
333
334 /* ------------------------------------------------------------------------- */
335 /* Draw a single marker symbol of the specified size and color */
336 /* ------------------------------------------------------------------------- */
msDrawMarkerSymbolIM(mapObj * map,imageObj * img,pointObj * p,styleObj * style,double scalefactor)337 void msDrawMarkerSymbolIM(mapObj *map, imageObj* img, pointObj *p, styleObj *style, double scalefactor)
338 {
339 symbolObj *symbol;
340 int ox, oy;
341 double size;
342
343 DEBUG_IF printf("msDrawMarkerSymbolIM\n<BR>");
344
345 /* skip this, we don't do text */
346
347
348
349 if(!p) return;
350
351
352 if(style->symbol > map->symbolset.numsymbols || style->symbol < 0) return; /* no such symbol, 0 is OK */
353 symbol = map->symbolset.symbol[style->symbol];
354 ox = style->offsetx*scalefactor;
355 oy = style->offsety*scalefactor;
356 if(style->size == -1) {
357 size = msSymbolGetDefaultSize( symbol );
358 size = MS_NINT(size*scalefactor);
359 } else
360 size = MS_NINT(style->size*scalefactor);
361 size = MS_MAX(size, style->minsize*img->resolutionfactor);
362 size = MS_MIN(size, style->maxsize*img->resolutionfactor);
363
364 if(size < 1) return; /* size too small */
365
366 /* DEBUG_IF printf(".%d.%d.%d.", symbol->type, style->symbol, fc); */
367 if(style->symbol == 0) { /* simply draw a single pixel of the specified color */
368
369 if (dxf) {
370 if (dxf==2)
371 im_iprintf (&imgStr, "POINT\n%.0f %.0f\n%d\n",
372 p->x + ox, p->y + oy, matchdxfcolor(style->color));
373 else
374 im_iprintf (&imgStr,
375 " 0\nPOINT\n 10\n%f\n 20\n%f\n 30\n0.0\n"
376 " 62\n%6d\n 8\n%s\n",
377 p->x + ox, p->y + oy, matchdxfcolor(style->color), lname);
378 } else {
379 im_iprintf (&imgStr, "<area ");
380 if (strcmp(symbolHrefFmt,"%.s")!=0) {
381 im_iprintf (&imgStr, "href=\"");
382 im_iprintf (&imgStr, symbolHrefFmt, lname);
383 im_iprintf (&imgStr, "\" ");
384 }
385 if (strcmp(symbolMOverFmt,"%.s")!=0) {
386 im_iprintf (&imgStr, "onMouseOver=\"");
387 im_iprintf (&imgStr, symbolMOverFmt, lname);
388 im_iprintf (&imgStr, "\" ");
389 }
390 if (strcmp(symbolMOutFmt,"%.s")!=0) {
391 im_iprintf (&imgStr, "onMouseOut=\"");
392 im_iprintf (&imgStr, symbolMOutFmt, lname);
393 im_iprintf (&imgStr, "\" ");
394 }
395 im_iprintf (&imgStr, "shape=\"circle\" coords=\"%.0f,%.0f, 3\" />\n",
396 p->x + ox, p->y + oy);
397 }
398
399 /* point2 = &( p->line[j].point[i] ); */
400 /* if(point1->y == point2->y) {} */
401 return;
402 }
403 DEBUG_IF printf("A");
404 switch(symbol->type) {
405 case(MS_SYMBOL_TRUETYPE):
406 DEBUG_IF printf("T");
407 break;
408 case(MS_SYMBOL_PIXMAP):
409 DEBUG_IF printf("P");
410 break;
411 case(MS_SYMBOL_VECTOR):
412 DEBUG_IF printf("V");
413 {
414 double d, offset_x, offset_y;
415
416 d = size/symbol->sizey;
417 offset_x = MS_NINT(p->x - d*.5*symbol->sizex + ox);
418 offset_y = MS_NINT(p->y - d*.5*symbol->sizey + oy);
419
420 /* For now I only render filled vector symbols in imagemap, and no */
421 /* dxf support available yet. */
422 if(symbol->filled && !dxf /* && fc >= 0 */ ) {
423 /* char *title=(p->numvalues) ? p->values[0] : ""; */
424 char *title = "";
425 int j;
426
427 im_iprintf (&imgStr, "<area ");
428 if (strcmp(symbolHrefFmt,"%.s")!=0) {
429 im_iprintf (&imgStr, "href=\"");
430 im_iprintf (&imgStr, symbolHrefFmt, lname);
431 im_iprintf (&imgStr, "\" ");
432 }
433 if (strcmp(symbolMOverFmt,"%.s")!=0) {
434 im_iprintf (&imgStr, "onMouseOver=\"");
435 im_iprintf (&imgStr, symbolMOverFmt, lname);
436 im_iprintf (&imgStr, "\" ");
437 }
438 if (strcmp(symbolMOutFmt,"%.s")!=0) {
439 im_iprintf (&imgStr, "onMouseOut=\"");
440 im_iprintf (&imgStr, symbolMOutFmt, lname);
441 im_iprintf (&imgStr, "\" ");
442 }
443
444 im_iprintf (&imgStr, "title=\"%s\" shape=\"poly\" coords=\"", title);
445
446 for(j=0; j < symbol->numpoints; j++) {
447 im_iprintf (&imgStr, "%s %d,%d", j == 0 ? "": ",",
448 MS_NINT(d*symbol->points[j].x + offset_x),
449 MS_NINT(d*symbol->points[j].y + offset_y) );
450 }
451 im_iprintf (&imgStr, "\" />\n");
452 } /* end of imagemap, filled case. */
453 }
454 break;
455
456 default:
457 DEBUG_IF printf("DEF");
458 break;
459 } /* end switch statement */
460
461 return;
462 }
463
464 /* ------------------------------------------------------------------------- */
465 /* Draw a line symbol of the specified size and color */
466 /* ------------------------------------------------------------------------- */
msDrawLineSymbolIM(mapObj * map,imageObj * img,shapeObj * p,styleObj * style,double scalefactor)467 void msDrawLineSymbolIM(mapObj *map, imageObj* img, shapeObj *p, styleObj *style, double scalefactor)
468 {
469 symbolObj *symbol;
470 int i,j,l;
471 char first = 1;
472 double size;
473 DEBUG_IF printf("msDrawLineSymbolIM<BR>\n");
474
475
476 if(!p) return;
477 if(p->numlines <= 0) return;
478
479 if(style->symbol > map->symbolset.numsymbols || style->symbol < 0) return; /* no such symbol, 0 is OK */
480 symbol = map->symbolset.symbol[style->symbol];
481 if(style->size == -1) {
482 size = msSymbolGetDefaultSize( symbol );
483 size = MS_NINT(size*scalefactor);
484 } else
485 size = MS_NINT(style->size*scalefactor);
486 size = MS_MAX(size, style->minsize*img->resolutionfactor);
487 size = MS_MIN(size, style->maxsize*img->resolutionfactor);
488
489 if (suppressEmpty && p->numvalues==0) return;/* suppress area with empty title */
490 if(style->symbol == 0) { /* just draw a single width line */
491 for(l=0,j=0; j<p->numlines; j++) {
492 if (dxf == 2) {
493 im_iprintf (&imgStr, "LINE\n%d\n", matchdxfcolor(style->color));
494 } else if (dxf) {
495 im_iprintf (&imgStr, " 0\nPOLYLINE\n 70\n 0\n 62\n%6d\n 8\n%s\n", matchdxfcolor(style->color), lname);
496 } else {
497 char *title;
498
499 first = 1;
500 title=(p->numvalues) ? p->values[0] : "";
501 im_iprintf (&imgStr, "<area ");
502 if (strcmp(polyHrefFmt,"%.s")!=0) {
503 im_iprintf (&imgStr, "href=\"");
504 im_iprintf (&imgStr, polyHrefFmt, title);
505 im_iprintf (&imgStr, "\" ");
506 }
507 if (strcmp(polyMOverFmt,"%.s")!=0) {
508 im_iprintf (&imgStr, "onMouseOver=\"");
509 im_iprintf (&imgStr, polyMOverFmt, title);
510 im_iprintf (&imgStr, "\" ");
511 }
512 if (strcmp(polyMOutFmt,"%.s")!=0) {
513 im_iprintf (&imgStr, "onMouseOut=\"");
514 im_iprintf (&imgStr, polyMOutFmt, title);
515 im_iprintf (&imgStr, "\" ");
516 }
517 im_iprintf (&imgStr, "title=\"%s\" shape=\"poly\" coords=\"", title);
518 }
519 /* point1 = &( p->line[j].point[p->line[j].numpoints-1] ); */
520 for(i=0; i < p->line[j].numpoints; i++,l++) {
521 if (dxf == 2) {
522 im_iprintf (&imgStr, "%.0f %.0f\n", p->line[j].point[i].x, p->line[j].point[i].y);
523 } else if (dxf) {
524 im_iprintf (&imgStr, " 0\nVERTEX\n 10\n%f\n 20\n%f\n 30\n%f\n", p->line[j].point[i].x, p->line[j].point[i].y, 0.0);
525 } else {
526 im_iprintf (&imgStr, "%s %.0f,%.0f", first ? "": ",", p->line[j].point[i].x, p->line[j].point[i].y);
527 }
528 first = 0;
529
530 /* point2 = &( p->line[j].point[i] ); */
531 /* if(point1->y == point2->y) {} */
532 }
533 im_iprintf (&imgStr, dxf ? (dxf == 2 ? "": " 0\nSEQEND\n") : "\" />\n");
534 }
535
536 /* DEBUG_IF printf ("%d, ",strlen(img->img.imagemap) ); */
537 return;
538 }
539
540 DEBUG_IF printf("-%d-",symbol->type);
541
542 return;
543 }
544
545
546 /* ------------------------------------------------------------------------- */
547 /* Draw a shade symbol of the specified size and color */
548 /* ------------------------------------------------------------------------- */
msDrawShadeSymbolIM(mapObj * map,imageObj * img,shapeObj * p,styleObj * style,double scalefactor)549 void msDrawShadeSymbolIM(mapObj *map, imageObj* img, shapeObj *p, styleObj *style, double scalefactor)
550 {
551 symbolObj *symbol;
552 int i,j,l;
553 char first = 1;
554 double size;
555
556 DEBUG_IF printf("msDrawShadeSymbolIM\n<BR>");
557 if(!p) return;
558 if(p->numlines <= 0) return;
559
560 symbol = map->symbolset.symbol[style->symbol];
561 if(style->size == -1) {
562 size = msSymbolGetDefaultSize( symbol );
563 size = MS_NINT(size*scalefactor);
564 } else
565 size = MS_NINT(style->size*scalefactor);
566 size = MS_MAX(size, style->minsize*img->resolutionfactor);
567 size = MS_MIN(size, style->maxsize*img->resolutionfactor);
568
569 if (suppressEmpty && p->numvalues==0) return;/* suppress area with empty title */
570 if(style->symbol == 0) { /* simply draw a single pixel of the specified color // */
571 for(l=0,j=0; j<p->numlines; j++) {
572 if (dxf == 2) {
573 im_iprintf (&imgStr, "POLY\n%d\n", matchdxfcolor(style->color));
574 } else if (dxf) {
575 im_iprintf (&imgStr, " 0\nPOLYLINE\n 73\n 1\n 62\n%6d\n 8\n%s\n", matchdxfcolor(style->color), lname);
576 } else {
577 char *title=(p->numvalues) ? p->values[0] : "";
578 first = 1;
579 im_iprintf (&imgStr, "<area ");
580 if (strcmp(polyHrefFmt,"%.s")!=0) {
581 im_iprintf (&imgStr, "href=\"");
582 im_iprintf (&imgStr, polyHrefFmt, title);
583 im_iprintf (&imgStr, "\" ");
584 }
585 if (strcmp(polyMOverFmt,"%.s")!=0) {
586 im_iprintf (&imgStr, "onMouseOver=\"");
587 im_iprintf (&imgStr, polyMOverFmt, title);
588 im_iprintf (&imgStr, "\" ");
589 }
590 if (strcmp(polyMOutFmt,"%.s")!=0) {
591 im_iprintf (&imgStr, "onMouseOut=\"");
592 im_iprintf (&imgStr, polyMOutFmt, title);
593 im_iprintf (&imgStr, "\" ");
594 }
595 im_iprintf (&imgStr, "title=\"%s\" shape=\"poly\" coords=\"", title);
596 }
597
598 /* point1 = &( p->line[j].point[p->line[j].numpoints-1] ); */
599 for(i=0; i < p->line[j].numpoints; i++,l++) {
600 if (dxf == 2) {
601 im_iprintf (&imgStr, "%.0f %.0f\n", p->line[j].point[i].x, p->line[j].point[i].y);
602 } else if (dxf) {
603 im_iprintf (&imgStr, " 0\nVERTEX\n 10\n%f\n 20\n%f\n 30\n%f\n", p->line[j].point[i].x, p->line[j].point[i].y, 0.0);
604 } else {
605 im_iprintf (&imgStr, "%s %.0f,%.0f", first ? "": ",", p->line[j].point[i].x, p->line[j].point[i].y);
606 }
607 first = 0;
608
609 /* point2 = &( p->line[j].point[i] ); */
610 /* if(point1->y == point2->y) {} */
611 }
612 im_iprintf (&imgStr, dxf ? (dxf == 2 ? "": " 0\nSEQEND\n") : "\" />\n");
613 }
614
615 return;
616 }
617 /* DEBUG_IF printf ("d"); */
618 DEBUG_IF printf("-%d-",symbol->type);
619 return;
620 }
621
622 /*
623 * Simply draws a label based on the label point and the supplied label object.
624 */
msDrawTextIM(mapObj * map,imageObj * img,pointObj labelPnt,char * string,labelObj * label,double scalefactor)625 int msDrawTextIM(mapObj *map, imageObj* img, pointObj labelPnt, char *string, labelObj *label, double scalefactor)
626 {
627 DEBUG_IF printf("msDrawText<BR>\n");
628 if(!string) return(0); /* not errors, just don't want to do anything */
629 if(strlen(string) == 0) return(0);
630 if(!dxf) return (0);
631
632 if (dxf == 2) {
633 im_iprintf (&imgStr, "TEXT\n%d\n%s\n%.0f\n%.0f\n%.0f\n" , matchdxfcolor(label->color), string, labelPnt.x, labelPnt.y, -label->angle);
634 } else if (dxf) {
635 im_iprintf (&imgStr, " 0\nTEXT\n 1\n%s\n 10\n%f\n 20\n%f\n 30\n0.0\n 40\n%f\n 50\n%f\n 62\n%6d\n 8\n%s\n 73\n 2\n 72\n 1\n" , string, labelPnt.x, labelPnt.y, label->size * scalefactor *100, -label->angle, matchdxfcolor(label->color), lname);
636 }
637 return(0);
638 }
639
640 /*
641 * Save an image to a file named filename, if filename is NULL it goes to stdout
642 */
643
msSaveImageIM(imageObj * img,const char * filename,outputFormatObj * format)644 int msSaveImageIM(imageObj* img, const char *filename, outputFormatObj *format )
645
646 {
647 FILE *stream;
648 char workbuffer[5000];
649 int nSize=0, size=0, iIndice=0;
650
651 DEBUG_IF printf("msSaveImageIM\n<BR>");
652
653 if(filename != NULL && strlen(filename) > 0) {
654 stream = fopen(filename, "wb");
655 if(!stream) {
656 msSetError(MS_IOERR, "(%s)", "msSaveImage()", filename);
657 return(MS_FAILURE);
658 }
659 } else { /* use stdout */
660
661 #ifdef _WIN32
662 /*
663 * Change stdout mode to binary on win32 platforms
664 */
665 if(_setmode( _fileno(stdout), _O_BINARY) == -1) {
666 msSetError(MS_IOERR, "Unable to change stdout to binary mode.", "msSaveImage()");
667 return(MS_FAILURE);
668 }
669 #endif
670 stream = stdout;
671 }
672
673 if( strcasecmp(format->driver,"imagemap") == 0 ) {
674 DEBUG_IF printf("ALLOCD %d<BR>\n", img->size);
675 /* DEBUG_IF printf("F %s<BR>\n", img->img.imagemap); */
676 DEBUG_IF printf("FLEN %d<BR>\n", (int)strlen(img->img.imagemap));
677 if (dxf == 2) {
678 msIO_fprintf(stream, "%s", layerlist);
679 } else if (dxf) {
680 msIO_fprintf(stream, " 0\nSECTION\n 2\nHEADER\n 9\n$ACADVER\n 1\nAC1009\n0\nENDSEC\n 0\nSECTION\n 2\nTABLES\n 0\nTABLE\n%s0\nENDTAB\n0\nENDSEC\n 0\nSECTION\n 2\nBLOCKS\n0\nENDSEC\n 0\nSECTION\n 2\nENTITIES\n", layerlist);
681 } else {
682 msIO_fprintf(stream, "<map name=\"%s\" width=\"%d\" height=\"%d\">\n", mapName, img->width, img->height);
683 }
684 nSize = sizeof(workbuffer);
685
686 size = strlen(img->img.imagemap);
687 if (size > nSize) {
688 iIndice = 0;
689 while ((iIndice + nSize) <= size) {
690 snprintf(workbuffer, sizeof(workbuffer), "%s", img->img.imagemap+iIndice );
691 workbuffer[nSize-1] = '\0';
692 msIO_fwrite(workbuffer, strlen(workbuffer), 1, stream);
693 iIndice +=nSize-1;
694 }
695 if (iIndice < size) {
696 sprintf(workbuffer, "%s", img->img.imagemap+iIndice );
697 msIO_fprintf(stream, "%s", workbuffer);
698 }
699 } else
700 msIO_fwrite(img->img.imagemap, size, 1, stream);
701 if( strcasecmp("OFF",msGetOutputFormatOption( format, "SKIPENDTAG", "OFF" )) == 0) {
702 if (dxf == 2)
703 msIO_fprintf(stream, "END");
704 else if (dxf)
705 msIO_fprintf(stream, "0\nENDSEC\n0\nEOF\n");
706 else
707 msIO_fprintf(stream, "</map>");
708 }
709 } else {
710 msSetError(MS_MISCERR, "Unknown output image type driver: %s.",
711 "msSaveImage()", format->driver );
712 return(MS_FAILURE);
713 }
714
715 if(filename != NULL && strlen(filename) > 0) fclose(stream);
716 return(MS_SUCCESS);
717 }
718
719
720 /*
721 * Free gdImagePtr
722 */
msFreeImageIM(imageObj * img)723 void msFreeImageIM(imageObj* img)
724 {
725 free(img->img.imagemap);
726 }
727
728