1 /*
2 
3  rl2symbolizer -- private SQL helper methods
4 
5  version 0.1, 2014 March 17
6 
7  Author: Sandro Furieri a.furieri@lqt.it
8 
9  -----------------------------------------------------------------------------
10 
11  Version: MPL 1.1/GPL 2.0/LGPL 2.1
12 
13  The contents of this file are subject to the Mozilla Public License Version
14  1.1 (the "License"); you may not use this file except in compliance with
15  the License. You may obtain a copy of the License at
16  http://www.mozilla.org/MPL/
17 
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22 
23 The Original Code is the SpatiaLite library
24 
25 The Initial Developer of the Original Code is Alessandro Furieri
26 
27 Portions created by the Initial Developer are Copyright (C) 2008-2013
28 the Initial Developer. All Rights Reserved.
29 
30 Alternatively, the contents of this file may be used under the terms of
31 either the GNU General Public License Version 2 or later (the "GPL"), or
32 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 in which case the provisions of the GPL or the LGPL are applicable instead
34 of those above. If you wish to allow use of your version of this file only
35 under the terms of either the GPL or the LGPL, and not to allow others to
36 use your version of this file under the terms of the MPL, indicate your
37 decision by deleting the provisions above and replace them with the notice
38 and other provisions required by the GPL or the LGPL. If you do not delete
39 the provisions above, a recipient may use your version of this file under
40 the terms of any one of the MPL, the GPL or the LGPL.
41 
42 */
43 
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <float.h>
48 #include <limits.h>
49 #include <stdint.h>
50 #include <inttypes.h>
51 
52 #ifdef _WIN32
53 #include <io.h>
54 #else
55 #include <unistd.h>
56 #endif
57 
58 #include "config.h"
59 
60 #include <libxml/parser.h>
61 
62 #ifdef LOADABLE_EXTENSION
63 #include "rasterlite2/sqlite.h"
64 #endif
65 
66 #include "rasterlite2/rasterlite2.h"
67 #include "rasterlite2_private.h"
68 
69 #include <spatialite/gaiaaux.h>
70 
71 #define RL2_UNUSED() if (argc || argv) argc = argc;
72 
73 static void
dummySilentError(void * ctx,const char * msg,...)74 dummySilentError (void *ctx, const char *msg, ...)
75 {
76 /* shutting up XML Errors */
77     if (ctx != NULL)
78 	ctx = NULL;		/* suppressing stupid compiler warnings (unused args) */
79     if (msg != NULL)
80 	ctx = NULL;		/* suppressing stupid compiler warnings (unused args) */
81 }
82 
83 static void
parse_sld_se_opacity(xmlNodePtr node,rl2PrivRasterStylePtr style)84 parse_sld_se_opacity (xmlNodePtr node, rl2PrivRasterStylePtr style)
85 {
86 /* parsing RasterSymbolizer Opacity */
87     while (node)
88       {
89 	  if (node->type == XML_ELEMENT_NODE)
90 	    {
91 		const char *name = (const char *) (node->name);
92 		if (strcmp (name, "Opacity") == 0)
93 		  {
94 		      xmlNodePtr child = node->children;
95 		      while (child)
96 			{
97 			    if (child->type == XML_TEXT_NODE
98 				&& child->content != NULL)
99 				style->opacity =
100 				    atof ((const char *) child->content);
101 			    child = child->next;
102 			}
103 		  }
104 	    }
105 	  node = node->next;
106       }
107 }
108 
109 static int
parse_sld_se_band_name(const char * name,unsigned char * band)110 parse_sld_se_band_name (const char *name, unsigned char *band)
111 {
112 /* attempting to parse a band name */
113     int digit = 0;
114     int nodigit = 0;
115     int i;
116     for (i = 0; i < (int) strlen (name); i++)
117       {
118 	  if (*(name + i) >= '0' && *(name + i) <= '9')
119 	      digit++;
120 	  else
121 	      nodigit++;
122       }
123     if (digit && !nodigit)
124       {
125 	  /* band identified by number */
126 	  int x = atoi (name) - 1;	/* first RL2 band has index 0 !!! */
127 	  if (x >= 0 && x <= 255)
128 	    {
129 		*band = x;
130 		return 1;
131 	    }
132       }
133     if (digit && nodigit)
134       {
135 	  if (strlen (name) > 9 && strncmp (name, "Band.band", 9) == 0)
136 	    {
137 		/* band identified by a string like "Band.band1" */
138 		int x = atoi (name + 9) - 1;	/* first RL2 band has index 0 !!! */
139 		if (x >= 0 && x <= 255)
140 		  {
141 		      *band = x;
142 		      return 1;
143 		  }
144 	    }
145       }
146     return 0;
147 }
148 
149 static int
parse_sld_se_channel_band(xmlNodePtr node,unsigned char * band)150 parse_sld_se_channel_band (xmlNodePtr node, unsigned char *band)
151 {
152 /* parsing RasterSymbolizer Channel -> Band */
153     while (node)
154       {
155 	  if (node->type == XML_ELEMENT_NODE)
156 	    {
157 		const char *name = (const char *) (node->name);
158 		if (strcmp (name, "SourceChannelName") == 0)
159 		  {
160 		      xmlNodePtr child = node->children;
161 		      while (child)
162 			{
163 			    if (child->type == XML_TEXT_NODE
164 				&& child->content != NULL)
165 			      {
166 				  const char *band_name =
167 				      (const char *) child->content;
168 				  if (parse_sld_se_band_name (band_name, band))
169 				      return 1;
170 				  else
171 				      return 0;
172 			      }
173 			    child = child->next;
174 			}
175 		  }
176 	    }
177 	  node = node->next;
178       }
179     return 0;
180 }
181 
182 static int
parse_sld_se_gamma_value(xmlNodePtr node,double * gamma)183 parse_sld_se_gamma_value (xmlNodePtr node, double *gamma)
184 {
185 /* parsing RasterSymbolizer GammaValue */
186     while (node)
187       {
188 	  if (node->type == XML_ELEMENT_NODE)
189 	    {
190 		const char *name = (const char *) (node->name);
191 		if (strcmp (name, "GammaValue") == 0)
192 		  {
193 		      xmlNodePtr child = node->children;
194 		      while (child)
195 			{
196 			    if (child->type == XML_TEXT_NODE
197 				&& child->content != NULL)
198 			      {
199 				  const char *gamma_value =
200 				      (const char *) child->content;
201 				  double gv = atof (gamma_value);
202 				  *gamma = gv;
203 				  return 1;
204 			      }
205 			    child = child->next;
206 			}
207 		  }
208 	    }
209 	  node = node->next;
210       }
211     return 0;
212 }
213 
214 static int
parse_sld_se_contrast_enhancement(xmlNodePtr node,unsigned char * mode,double * gamma)215 parse_sld_se_contrast_enhancement (xmlNodePtr node, unsigned char *mode,
216 				   double *gamma)
217 {
218 /* parsing RasterSymbolizer ContrastEnhancement */
219     while (node)
220       {
221 	  if (node->type == XML_ELEMENT_NODE)
222 	    {
223 		const char *name = (const char *) (node->name);
224 		if (strcmp (name, "ContrastEnhancement") == 0)
225 		  {
226 		      xmlNodePtr child = node->children;
227 		      while (child)
228 			{
229 			    if (child->type == XML_ELEMENT_NODE)
230 			      {
231 				  const char *xmode =
232 				      (const char *) (child->name);
233 				  if (strcmp (xmode, "Normalize") == 0)
234 				    {
235 					*mode =
236 					    RL2_CONTRAST_ENHANCEMENT_NORMALIZE;
237 					return 1;
238 				    }
239 				  if (strcmp (xmode, "Histogram") == 0)
240 				    {
241 					*mode =
242 					    RL2_CONTRAST_ENHANCEMENT_HISTOGRAM;
243 					return 1;
244 				    }
245 				  if (strcmp (xmode, "GammaValue") == 0)
246 				    {
247 					if (parse_sld_se_gamma_value
248 					    (child, gamma))
249 					  {
250 					      *mode =
251 						  RL2_CONTRAST_ENHANCEMENT_GAMMA;
252 					      return 1;
253 					  }
254 					return 1;
255 				    }
256 			      }
257 			    child = child->next;
258 			}
259 		      return 0;
260 		  }
261 	    }
262 	  node = node->next;
263       }
264     return 1;
265 }
266 
267 static int
parse_sld_se_channels(xmlNodePtr node,rl2PrivRasterStylePtr style)268 parse_sld_se_channels (xmlNodePtr node, rl2PrivRasterStylePtr style)
269 {
270 /* parsing RasterSymbolizer Channels */
271     int has_red = 0;
272     int has_green = 0;
273     int has_blue = 0;
274     int has_gray = 0;
275     unsigned char red;
276     unsigned char green;
277     unsigned char blue;
278     unsigned char gray;
279     unsigned char red_contrast = RL2_CONTRAST_ENHANCEMENT_NONE;
280     unsigned char green_contrast = RL2_CONTRAST_ENHANCEMENT_NONE;
281     unsigned char blue_contrast = RL2_CONTRAST_ENHANCEMENT_NONE;
282     unsigned char gray_contrast = RL2_CONTRAST_ENHANCEMENT_NONE;
283     double red_gamma = 1.0;
284     double green_gamma = 1.0;
285     double blue_gamma = 1.0;
286     double gray_gamma = 1.0;
287     while (node)
288       {
289 	  if (node->type == XML_ELEMENT_NODE)
290 	    {
291 		const char *name = (const char *) (node->name);
292 		if (strcmp (name, "RedChannel") == 0)
293 		  {
294 		      has_red = 1;
295 		      if (!parse_sld_se_channel_band (node->children, &red))
296 			  return 0;
297 		      if (!parse_sld_se_contrast_enhancement
298 			  (node->children, &red_contrast, &red_gamma))
299 			  return 0;
300 		  }
301 		if (strcmp (name, "GreenChannel") == 0)
302 		  {
303 		      has_green = 1;
304 		      if (!parse_sld_se_channel_band (node->children, &green))
305 			  return 0;
306 		      if (!parse_sld_se_contrast_enhancement
307 			  (node->children, &green_contrast, &green_gamma))
308 			  return 0;
309 		  }
310 		if (strcmp (name, "BlueChannel") == 0)
311 		  {
312 		      has_blue = 1;
313 		      if (!parse_sld_se_channel_band (node->children, &blue))
314 			  return 0;
315 		      if (!parse_sld_se_contrast_enhancement
316 			  (node->children, &blue_contrast, &blue_gamma))
317 			  return 0;
318 		  }
319 		if (strcmp (name, "GrayChannel") == 0)
320 		  {
321 		      has_gray = 1;
322 		      if (!parse_sld_se_channel_band (node->children, &gray))
323 			  return 0;
324 		      if (!parse_sld_se_contrast_enhancement
325 			  (node->children, &gray_contrast, &gray_gamma))
326 			  return 0;
327 		  }
328 	    }
329 	  node = node->next;
330       }
331     if (has_red && has_green && has_blue && !has_gray)
332       {
333 	  /* triple band selection */
334 	  style->bandSelection = malloc (sizeof (rl2PrivBandSelection));
335 	  style->bandSelection->selectionType = RL2_BAND_SELECTION_TRIPLE;
336 	  style->bandSelection->redBand = red;
337 	  style->bandSelection->greenBand = green;
338 	  style->bandSelection->blueBand = blue;
339 	  style->bandSelection->redContrast = red_contrast;
340 	  style->bandSelection->redGamma = red_gamma;
341 	  style->bandSelection->greenContrast = green_contrast;
342 	  style->bandSelection->greenGamma = green_gamma;
343 	  style->bandSelection->blueContrast = blue_contrast;
344 	  style->bandSelection->blueGamma = blue_gamma;
345 	  return 1;
346       }
347     if (!has_red && !has_green && !has_blue && has_gray)
348       {
349 	  /* mono band selection */
350 	  if (gray_gamma < 0.0)
351 	      gray_gamma = 0.0;
352 	  if (gray_gamma > 1.0)
353 	      gray_gamma = 1.0;
354 	  style->bandSelection = malloc (sizeof (rl2PrivBandSelection));
355 	  style->bandSelection->selectionType = RL2_BAND_SELECTION_MONO;
356 	  style->bandSelection->grayBand = gray;
357 	  style->bandSelection->grayContrast = gray_contrast;
358 	  style->bandSelection->grayGamma = gray_gamma;
359 	  return 1;
360       }
361 
362     return 0;
363 }
364 
365 static int
parse_hex(unsigned char hi,unsigned char lo,unsigned char * val)366 parse_hex (unsigned char hi, unsigned char lo, unsigned char *val)
367 {
368 /* attempting to parse an hexadecimal byte */
369     unsigned char value;
370     switch (hi)
371       {
372       case '0':
373 	  value = 0;
374 	  break;
375       case '1':
376 	  value = 1 * 16;
377 	  break;
378       case '2':
379 	  value = 2 * 16;
380 	  break;
381       case '3':
382 	  value = 3 * 16;
383 	  break;
384       case '4':
385 	  value = 4 * 16;
386 	  break;
387       case '5':
388 	  value = 5 * 16;
389 	  break;
390       case '6':
391 	  value = 6 * 16;
392 	  break;
393       case '7':
394 	  value = 7 * 16;
395 	  break;
396       case '8':
397 	  value = 8 * 16;
398 	  break;
399       case '9':
400 	  value = 9 * 16;
401 	  break;
402       case 'a':
403       case 'A':
404 	  value = 10 * 16;
405 	  break;
406       case 'b':
407       case 'B':
408 	  value = 11 * 16;
409 	  break;
410       case 'c':
411       case 'C':
412 	  value = 12 * 16;
413 	  break;
414       case 'd':
415       case 'D':
416 	  value = 13 * 16;
417 	  break;
418       case 'e':
419       case 'E':
420 	  value = 14 * 16;
421 	  break;
422       case 'f':
423       case 'F':
424 	  value = 15 * 16;
425 	  break;
426       default:
427 	  return 0;
428 	  break;
429       };
430     switch (lo)
431       {
432       case '0':
433 	  value += 0;
434 	  break;
435       case '1':
436 	  value += 1;
437 	  break;
438       case '2':
439 	  value += 2;
440 	  break;
441       case '3':
442 	  value += 3;
443 	  break;
444       case '4':
445 	  value += 4;
446 	  break;
447       case '5':
448 	  value += 5;
449 	  break;
450       case '6':
451 	  value += 6;
452 	  break;
453       case '7':
454 	  value += 7;
455 	  break;
456       case '8':
457 	  value += 8;
458 	  break;
459       case '9':
460 	  value += 9;
461 	  break;
462       case 'a':
463       case 'A':
464 	  value += 10;
465 	  break;
466       case 'b':
467       case 'B':
468 	  value += 11;
469 	  break;
470       case 'c':
471       case 'C':
472 	  value += 12;
473 	  break;
474       case 'd':
475       case 'D':
476 	  value += 13;
477 	  break;
478       case 'e':
479       case 'E':
480 	  value += 14;
481 	  break;
482       case 'f':
483       case 'F':
484 	  value += 15;
485 	  break;
486       default:
487 	  return 0;
488 	  break;
489       };
490     *val = value;
491     return 1;
492 }
493 
494 static int
parse_sld_se_color(const char * color,unsigned char * red,unsigned char * green,unsigned char * blue)495 parse_sld_se_color (const char *color, unsigned char *red, unsigned char *green,
496 		    unsigned char *blue)
497 {
498 /* attempting to parse a #RRGGBB hexadecimal color */
499     unsigned char r;
500     unsigned char g;
501     unsigned char b;
502     if (strlen (color) != 7)
503 	return 0;
504     if (*color != '#')
505 	return 0;
506     if (!parse_hex (*(color + 1), *(color + 2), &r))
507 	return 0;
508     if (!parse_hex (*(color + 3), *(color + 4), &g))
509 	return 0;
510     if (!parse_hex (*(color + 5), *(color + 6), &b))
511 	return 0;
512     *red = r;
513     *green = g;
514     *blue = b;
515     return 1;
516 }
517 
518 static int
parse_sld_se_channel_selection(xmlNodePtr node,rl2PrivRasterStylePtr style)519 parse_sld_se_channel_selection (xmlNodePtr node, rl2PrivRasterStylePtr style)
520 {
521 /* parsing RasterSymbolizer ChannelSelection */
522     while (node)
523       {
524 	  if (node->type == XML_ELEMENT_NODE)
525 	    {
526 		const char *name = (const char *) (node->name);
527 		if (strcmp (name, "ChannelSelection") == 0)
528 		  {
529 		      if (parse_sld_se_channels (node->children, style))
530 			  return 1;
531 		      else
532 			  return 0;
533 		  }
534 	    }
535 	  node = node->next;
536       }
537     return 1;
538 }
539 
540 static int
parse_sld_se_categorize(xmlNodePtr node,rl2PrivRasterStylePtr style)541 parse_sld_se_categorize (xmlNodePtr node, rl2PrivRasterStylePtr style)
542 {
543 /* parsing RasterSymbolizer ColorMap Categorize */
544     struct _xmlAttr *attr;
545     xmlNodePtr child;
546     xmlNodePtr text;
547 
548     attr = node->properties;
549     while (attr != NULL)
550       {
551 	  /* attributes */
552 	  if (attr->type == XML_ATTRIBUTE_NODE)
553 	    {
554 		const char *name = (const char *) (attr->name);
555 		if (strcmp (name, "fallbackValue") == 0)
556 		  {
557 		      xmlNode *text = attr->children;
558 		      if (text != NULL)
559 			{
560 			    if (text->type == XML_TEXT_NODE)
561 			      {
562 				  const char *color =
563 				      (const char *) (text->content);
564 				  if (color != NULL)
565 				    {
566 					unsigned char red;
567 					unsigned char green;
568 					unsigned char blue;
569 					if (parse_sld_se_color
570 					    (color, &red, &green, &blue))
571 					  {
572 					      style->categorize->dfltRed = red;
573 					      style->categorize->dfltGreen =
574 						  green;
575 					      style->categorize->dfltBlue =
576 						  blue;
577 					  }
578 				    }
579 			      }
580 			}
581 		  }
582 	    }
583 	  attr = attr->next;
584       }
585 
586     child = node->children;
587     while (child)
588       {
589 	  if (child->type == XML_ELEMENT_NODE)
590 	    {
591 		const char *name = (const char *) (child->name);
592 		if (strcmp (name, "Value") == 0)
593 		  {
594 		      text = child->children;
595 		      while (text)
596 			{
597 			    if (text->type == XML_TEXT_NODE)
598 			      {
599 				  const char *color =
600 				      (const char *) (text->content);
601 				  if (color != NULL)
602 				    {
603 					unsigned char red;
604 					unsigned char green;
605 					unsigned char blue;
606 					if (parse_sld_se_color
607 					    (color, &red, &green, &blue))
608 					  {
609 					      if (style->categorize->last ==
610 						  NULL)
611 						{
612 						    style->categorize->baseRed =
613 							red;
614 						    style->
615 							categorize->baseGreen =
616 							green;
617 						    style->
618 							categorize->baseBlue =
619 							blue;
620 						}
621 					      else
622 						{
623 						    style->categorize->
624 							last->red = red;
625 						    style->categorize->
626 							last->green = green;
627 						    style->categorize->
628 							last->blue = blue;
629 						}
630 					  }
631 					else
632 					    return 0;
633 				    }
634 			      }
635 			    text = text->next;
636 			}
637 		  }
638 		if (strcmp (name, "Threshold") == 0)
639 		  {
640 		      text = child->children;
641 		      while (text)
642 			{
643 			    if (text->type == XML_TEXT_NODE)
644 			      {
645 				  const char *value =
646 				      (const char *) (text->content);
647 				  if (value != NULL)
648 				    {
649 					rl2PrivColorMapPointPtr pt =
650 					    malloc (sizeof
651 						    (rl2PrivColorMapPoint));
652 					pt->value = atof (value);
653 					pt->red = 0;
654 					pt->green = 0;
655 					pt->blue = 0;
656 					pt->next = NULL;
657 					if (style->categorize->first == NULL)
658 					    style->categorize->first = pt;
659 					if (style->categorize->last != NULL)
660 					    style->categorize->last->next = pt;
661 					style->categorize->last = pt;
662 				    }
663 			      }
664 			    text = text->next;
665 			}
666 		  }
667 	    }
668 	  child = child->next;
669       }
670     return 1;
671 }
672 
673 static int
parse_sld_se_interpolation_point_data(xmlNodePtr node,double * data)674 parse_sld_se_interpolation_point_data (xmlNodePtr node, double *data)
675 {
676 /* parsing RasterSymbolizer ColorMap InterpolationPoint Data */
677     while (node)
678       {
679 	  if (node->type == XML_TEXT_NODE)
680 	    {
681 		const char *value = (const char *) (node->content);
682 		if (value != NULL)
683 		  {
684 		      *data = atof (value);
685 		      return 1;
686 		  }
687 	    }
688 	  node = node->next;
689       }
690     return 0;
691 }
692 
693 static int
parse_sld_se_interpolation_point_value(xmlNodePtr node,unsigned char * red,unsigned char * green,unsigned char * blue)694 parse_sld_se_interpolation_point_value (xmlNodePtr node, unsigned char *red,
695 					unsigned char *green,
696 					unsigned char *blue)
697 {
698 /* parsing RasterSymbolizer ColorMap InterpolationPoint Value */
699     while (node)
700       {
701 	  if (node->type == XML_TEXT_NODE)
702 	    {
703 		const char *color = (const char *) (node->content);
704 		if (color != NULL)
705 		  {
706 		      unsigned char r;
707 		      unsigned char g;
708 		      unsigned char b;
709 		      if (parse_sld_se_color (color, &r, &g, &b))
710 			{
711 			    *red = r;
712 			    *green = g;
713 			    *blue = b;
714 			    return 1;
715 			}
716 		  }
717 	    }
718 	  node = node->next;
719       }
720     return 0;
721 }
722 
723 static int
parse_sld_se_interpolation_point(xmlNodePtr node,rl2PrivRasterStylePtr style)724 parse_sld_se_interpolation_point (xmlNodePtr node, rl2PrivRasterStylePtr style)
725 {
726 /* parsing RasterSymbolizer ColorMap InterpolationPoint */
727     double value;
728     unsigned char red;
729     unsigned char green;
730     unsigned char blue;
731     int has_data = 0;
732     int has_value = 0;
733 
734     while (node)
735       {
736 	  if (node->type == XML_ELEMENT_NODE)
737 	    {
738 		const char *name = (const char *) (node->name);
739 		if (strcmp (name, "Data") == 0)
740 		  {
741 		      has_data = 1;
742 		      if (!parse_sld_se_interpolation_point_data
743 			  (node->children, &value))
744 			  return 0;
745 		  }
746 		if (strcmp (name, "Value") == 0)
747 		  {
748 		      has_value = 1;
749 		      if (!parse_sld_se_interpolation_point_value
750 			  (node->children, &red, &green, &blue))
751 			  return 0;
752 		  }
753 	    }
754 	  node = node->next;
755       }
756 
757     if (has_data && has_value)
758       {
759 	  rl2PrivColorMapPointPtr pt = malloc (sizeof (rl2PrivColorMapPoint));
760 	  pt->value = value;
761 	  pt->red = red;
762 	  pt->green = green;
763 	  pt->blue = blue;
764 	  pt->next = NULL;
765 	  if (style->interpolate->first == NULL)
766 	      style->interpolate->first = pt;
767 	  if (style->interpolate->last != NULL)
768 	      style->interpolate->last->next = pt;
769 	  style->interpolate->last = pt;
770 	  return 1;
771       }
772     return 0;
773 }
774 
775 static int
parse_sld_se_interpolate(xmlNodePtr node,rl2PrivRasterStylePtr style)776 parse_sld_se_interpolate (xmlNodePtr node, rl2PrivRasterStylePtr style)
777 {
778 /* parsing RasterSymbolizer ColorMap Interpolate */
779     struct _xmlAttr *attr;
780     xmlNodePtr child;
781 
782     attr = node->properties;
783     while (attr != NULL)
784       {
785 	  /* attributes */
786 	  if (attr->type == XML_ATTRIBUTE_NODE)
787 	    {
788 		const char *name = (const char *) (attr->name);
789 		if (strcmp (name, "fallbackValue") == 0)
790 		  {
791 		      xmlNode *text = attr->children;
792 		      if (text != NULL)
793 			{
794 			    if (text->type == XML_TEXT_NODE)
795 			      {
796 				  const char *color =
797 				      (const char *) (text->content);
798 				  if (color != NULL)
799 				    {
800 					unsigned char red;
801 					unsigned char green;
802 					unsigned char blue;
803 					if (parse_sld_se_color
804 					    (color, &red, &green, &blue))
805 					  {
806 					      style->interpolate->dfltRed = red;
807 					      style->interpolate->dfltGreen =
808 						  green;
809 					      style->interpolate->dfltBlue =
810 						  blue;
811 					  }
812 				    }
813 			      }
814 			}
815 		  }
816 	    }
817 	  attr = attr->next;
818       }
819 
820     child = node->children;
821     while (child)
822       {
823 	  if (child->type == XML_ELEMENT_NODE)
824 	    {
825 		const char *name = (const char *) (child->name);
826 		if (strcmp (name, "InterpolationPoint") == 0)
827 		  {
828 		      if (!parse_sld_se_interpolation_point
829 			  (child->children, style))
830 			  return 0;
831 		  }
832 	    }
833 	  child = child->next;
834       }
835     return 1;
836 }
837 
838 static int
parse_sld_se_color_map(xmlNodePtr node,rl2PrivRasterStylePtr style)839 parse_sld_se_color_map (xmlNodePtr node, rl2PrivRasterStylePtr style)
840 {
841 /* parsing RasterSymbolizer ColorMap */
842     while (node)
843       {
844 	  if (node->type == XML_ELEMENT_NODE)
845 	    {
846 		const char *name = (const char *) (node->name);
847 		if (strcmp (name, "ColorMap") == 0)
848 		  {
849 		      xmlNodePtr child = node->children;
850 		      while (child)
851 			{
852 			    if (child->type == XML_ELEMENT_NODE)
853 			      {
854 				  const char *xmode =
855 				      (const char *) (child->name);
856 				  if (strcmp (xmode, "Interpolate") == 0)
857 				    {
858 					style->interpolate =
859 					    malloc (sizeof
860 						    (rl2PrivColorMapInterpolate));
861 					style->interpolate->first = NULL;
862 					style->interpolate->last = NULL;
863 					style->interpolate->dfltRed = 0;
864 					style->interpolate->dfltGreen = 0;
865 					style->interpolate->dfltBlue = 0;
866 					if (parse_sld_se_interpolate
867 					    (child, style))
868 					    return 1;
869 				    }
870 				  if (strcmp (xmode, "Categorize") == 0)
871 				    {
872 					style->categorize =
873 					    malloc (sizeof
874 						    (rl2PrivColorMapCategorize));
875 					style->categorize->first = NULL;
876 					style->categorize->last = NULL;
877 					style->categorize->dfltRed = 0;
878 					style->categorize->dfltGreen = 0;
879 					style->categorize->dfltBlue = 0;
880 					style->categorize->baseRed = 0;
881 					style->categorize->baseGreen = 0;
882 					style->categorize->baseBlue = 0;
883 					if (parse_sld_se_categorize
884 					    (child, style))
885 					    return 1;
886 				    }
887 			      }
888 			    child = child->next;
889 			}
890 		      return 0;
891 		  }
892 	    }
893 	  node = node->next;
894       }
895     return 1;
896 }
897 
898 static void
parse_sld_se_shaded_relief(xmlNodePtr node,rl2PrivRasterStylePtr style)899 parse_sld_se_shaded_relief (xmlNodePtr node, rl2PrivRasterStylePtr style)
900 {
901 /* parsing RasterSymbolizer ShadedRelief */
902     xmlNodePtr text;
903 
904     while (node)
905       {
906 	  if (node->type == XML_ELEMENT_NODE)
907 	    {
908 		const char *name = (const char *) (node->name);
909 		if (strcmp (name, "ShadedRelief") == 0)
910 		  {
911 		      xmlNodePtr child = node->children;
912 		      while (child)
913 			{
914 			    if (child->type == XML_ELEMENT_NODE)
915 			      {
916 				  const char *xmode =
917 				      (const char *) (child->name);
918 				  if (strcmp (xmode, "BrightnessOnly") == 0)
919 				    {
920 					text = child->children;
921 					while (text)
922 					  {
923 					      if (text->type == XML_TEXT_NODE)
924 						{
925 						    const char *value =
926 							(const char
927 							 *) (text->content);
928 						    if (value != NULL)
929 							style->brightnessOnly =
930 							    atoi (value);
931 						}
932 					      text = text->next;
933 					  }
934 				    }
935 				  if (strcmp (xmode, "ReliefFactor") == 0)
936 				    {
937 					text = child->children;
938 					while (text)
939 					  {
940 					      if (text->type == XML_TEXT_NODE)
941 						{
942 						    const char *value =
943 							(const char
944 							 *) (text->content);
945 						    if (value != NULL)
946 							style->reliefFactor =
947 							    atof (value);
948 						}
949 					      text = text->next;
950 					  }
951 				    }
952 			      }
953 			    child = child->next;
954 			}
955 		      style->shadedRelief = 1;
956 		  }
957 	    }
958 	  node = node->next;
959       }
960 }
961 
962 static int
parse_raster_symbolizer(xmlNodePtr node,rl2PrivRasterStylePtr style)963 parse_raster_symbolizer (xmlNodePtr node, rl2PrivRasterStylePtr style)
964 {
965 /* attempting to parse an SLD/SE RasterSymbolizer */
966     parse_sld_se_opacity (node->children, style);
967     if (!parse_sld_se_channel_selection (node->children, style))
968 	return 0;
969     if (!parse_sld_se_color_map (node->children, style))
970 	return 0;
971     if (!parse_sld_se_contrast_enhancement
972 	(node->children, &(style->contrastEnhancement), &(style->gammaValue)))
973 	return 0;
974     parse_sld_se_shaded_relief (node->children, style);
975     return 1;
976 }
977 
978 static int
find_raster_symbolizer(xmlNodePtr node,rl2PrivRasterStylePtr style,int * loop)979 find_raster_symbolizer (xmlNodePtr node, rl2PrivRasterStylePtr style, int *loop)
980 {
981 /* recursively searching an SLD/SE RasterSymbolizer */
982     while (node)
983       {
984 	  if (node->type == XML_ELEMENT_NODE)
985 	    {
986 		const char *name = (const char *) (node->name);
987 		if (strcmp (name, "RasterSymbolizer") == 0)
988 		  {
989 		      int ret = parse_raster_symbolizer (node, style);
990 		      *loop = 0;
991 		      return ret;
992 		  }
993 		if (strcmp (name, "CoverageStyle") == 0 ||
994 		    strcmp (name, "Rule") == 0)
995 		  {
996 		      int ret =
997 			  find_raster_symbolizer (node->children, style, loop);
998 		      if (*loop == 0)
999 			  return ret;
1000 		  }
1001 	    }
1002 	  node = node->next;
1003       }
1004     return 0;
1005 }
1006 
1007 RL2_PRIVATE rl2RasterStylePtr
raster_style_from_sld_se_xml(char * name,char * title,char * abstract,unsigned char * xml)1008 raster_style_from_sld_se_xml (char *name, char *title, char *abstract,
1009 			      unsigned char *xml)
1010 {
1011 /* attempting to build a RasterStyle object from an SLD/SE XML style */
1012     rl2PrivRasterStylePtr style = NULL;
1013     xmlDocPtr xml_doc = NULL;
1014     xmlNodePtr root;
1015     int loop = 1;
1016     xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) dummySilentError;
1017 
1018     style = malloc (sizeof (rl2PrivRasterStyle));
1019     if (style == NULL)
1020 	return NULL;
1021     style->name = name;
1022     style->title = title;
1023     style->abstract = abstract;
1024     style->opacity = 1.0;
1025     style->bandSelection = NULL;
1026     style->categorize = NULL;
1027     style->interpolate = NULL;
1028     style->contrastEnhancement = RL2_CONTRAST_ENHANCEMENT_NONE;
1029     style->gammaValue = 1.0;
1030     style->shadedRelief = 0;
1031     style->brightnessOnly = 0;
1032     style->reliefFactor = 55.0;
1033 
1034 /* parsing the XML document */
1035     xmlSetGenericErrorFunc (NULL, silentError);
1036     xml_doc =
1037 	xmlReadMemory ((const char *) xml, strlen ((const char *) xml),
1038 		       "noname.xml", NULL, 0);
1039     if (xml_doc == NULL)
1040       {
1041 	  /* parsing error; not a well-formed XML */
1042 	  goto error;
1043       }
1044     root = xmlDocGetRootElement (xml_doc);
1045     if (root == NULL)
1046 	goto error;
1047     if (!find_raster_symbolizer (root, style, &loop))
1048 	goto error;
1049     xmlFreeDoc (xml_doc);
1050     free (xml);
1051     xml = NULL;
1052 
1053     if (style->name == NULL)
1054 	goto error;
1055 
1056     return (rl2RasterStylePtr) style;
1057 
1058   error:
1059     if (xml != NULL)
1060 	free (xml);
1061     if (xml_doc != NULL)
1062 	xmlFreeDoc (xml_doc);
1063     if (style != NULL)
1064 	rl2_destroy_raster_style ((rl2RasterStylePtr) style);
1065     return NULL;
1066 }
1067 
1068 RL2_DECLARE void
rl2_destroy_raster_style(rl2RasterStylePtr style)1069 rl2_destroy_raster_style (rl2RasterStylePtr style)
1070 {
1071 /* destroying a RasterStyle object */
1072     rl2PrivColorMapPointPtr pC;
1073     rl2PrivColorMapPointPtr pCn;
1074     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1075     if (stl == NULL)
1076 	return;
1077 
1078     if (stl->name != NULL)
1079 	free (stl->name);
1080     if (stl->title != NULL)
1081 	free (stl->title);
1082     if (stl->abstract != NULL)
1083 	free (stl->abstract);
1084     if (stl->bandSelection != NULL)
1085 	free (stl->bandSelection);
1086     if (stl->categorize != NULL)
1087       {
1088 	  pC = stl->categorize->first;
1089 	  while (pC != NULL)
1090 	    {
1091 		pCn = pC->next;
1092 		free (pC);
1093 		pC = pCn;
1094 	    }
1095 	  free (stl->categorize);
1096       }
1097     if (stl->interpolate != NULL)
1098       {
1099 	  pC = stl->interpolate->first;
1100 	  while (pC != NULL)
1101 	    {
1102 		pCn = pC->next;
1103 		free (pC);
1104 		pC = pCn;
1105 	    }
1106 	  free (stl->interpolate);
1107       }
1108     free (stl);
1109 }
1110 
1111 RL2_DECLARE const char *
rl2_get_raster_style_name(rl2RasterStylePtr style)1112 rl2_get_raster_style_name (rl2RasterStylePtr style)
1113 {
1114 /* return the RasterStyle Name */
1115     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1116     if (stl == NULL)
1117 	return NULL;
1118     return stl->name;
1119 }
1120 
1121 RL2_DECLARE const char *
rl2_get_raster_style_title(rl2RasterStylePtr style)1122 rl2_get_raster_style_title (rl2RasterStylePtr style)
1123 {
1124 /* return the RasterStyle Title */
1125     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1126     if (stl == NULL)
1127 	return NULL;
1128     return stl->title;
1129 }
1130 
1131 RL2_DECLARE const char *
rl2_get_raster_style_abstract(rl2RasterStylePtr style)1132 rl2_get_raster_style_abstract (rl2RasterStylePtr style)
1133 {
1134 /* return the RasterStyle Abstract */
1135     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1136     if (stl == NULL)
1137 	return NULL;
1138     return stl->abstract;
1139 }
1140 
1141 RL2_DECLARE int
rl2_get_raster_style_opacity(rl2RasterStylePtr style,double * opacity)1142 rl2_get_raster_style_opacity (rl2RasterStylePtr style, double *opacity)
1143 {
1144 /* return the RasterStyle Opacity */
1145     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1146     if (stl == NULL)
1147 	return RL2_ERROR;
1148     *opacity = stl->opacity;
1149     return RL2_OK;
1150 }
1151 
1152 RL2_DECLARE int
rl2_is_raster_style_mono_band_selected(rl2RasterStylePtr style,int * selected)1153 rl2_is_raster_style_mono_band_selected (rl2RasterStylePtr style, int *selected)
1154 {
1155 /* return if the RasterStyle has a MonoBand selection */
1156     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1157     if (stl == NULL)
1158 	return RL2_ERROR;
1159     if (stl->shadedRelief)
1160       {
1161 	  /* Shaded Relief */
1162 	  *selected = 1;
1163 	  return RL2_OK;
1164       }
1165     if (stl->bandSelection == NULL)
1166       {
1167 	  if (stl->categorize != NULL)
1168 	    {
1169 		/* Categorize Color Map */
1170 		*selected = 1;
1171 		return RL2_OK;
1172 	    }
1173 	  if (stl->interpolate != NULL)
1174 	    {
1175 		/* Interpolate Color Map */
1176 		*selected = 1;
1177 		return RL2_OK;
1178 	    }
1179 	  if (stl->contrastEnhancement == RL2_CONTRAST_ENHANCEMENT_NORMALIZE ||
1180 	      stl->contrastEnhancement == RL2_CONTRAST_ENHANCEMENT_HISTOGRAM ||
1181 	      stl->contrastEnhancement == RL2_CONTRAST_ENHANCEMENT_GAMMA)
1182 	    {
1183 		/* Contrast Enhancement */
1184 		*selected = 1;
1185 		return RL2_OK;
1186 	    }
1187       }
1188     if (stl->bandSelection == NULL)
1189 	*selected = 0;
1190     else if (stl->bandSelection->selectionType == RL2_BAND_SELECTION_MONO)
1191 	*selected = 1;
1192     else
1193 	*selected = 0;
1194     return RL2_OK;
1195 }
1196 
1197 RL2_DECLARE int
rl2_get_raster_style_mono_band_selection(rl2RasterStylePtr style,unsigned char * gray_band)1198 rl2_get_raster_style_mono_band_selection (rl2RasterStylePtr style,
1199 					  unsigned char *gray_band)
1200 {
1201 /* return the RasterStyle MonoBand selection */
1202     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1203     if (stl == NULL)
1204 	return RL2_ERROR;
1205     if (stl->bandSelection == NULL)
1206       {
1207 	  if (stl->categorize != NULL)
1208 	    {
1209 		/* Categorize Color Map */
1210 		*gray_band = 0;
1211 		return RL2_OK;
1212 	    }
1213 	  if (stl->interpolate != NULL)
1214 	    {
1215 		/* Interpolate Color Map */
1216 		*gray_band = 0;
1217 		return RL2_OK;
1218 	    }
1219 	  /* Interpolate Color Map */
1220 	  *gray_band = 0;
1221 	  return RL2_OK;
1222       }
1223     if (stl->bandSelection == NULL)
1224 	return RL2_ERROR;
1225     else if (stl->bandSelection->selectionType == RL2_BAND_SELECTION_MONO)
1226       {
1227 	  *gray_band = stl->bandSelection->grayBand;
1228 	  return RL2_OK;
1229       }
1230     else
1231 	return RL2_ERROR;
1232 }
1233 
1234 RL2_DECLARE int
rl2_is_raster_style_triple_band_selected(rl2RasterStylePtr style,int * selected)1235 rl2_is_raster_style_triple_band_selected (rl2RasterStylePtr style,
1236 					  int *selected)
1237 {
1238 /* return if the RasterStyle has a TripleBand selection */
1239     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1240     if (stl == NULL)
1241 	return RL2_ERROR;
1242     if (stl->bandSelection == NULL)
1243       {
1244 	  if (stl->contrastEnhancement == RL2_CONTRAST_ENHANCEMENT_NORMALIZE ||
1245 	      stl->contrastEnhancement == RL2_CONTRAST_ENHANCEMENT_HISTOGRAM ||
1246 	      stl->contrastEnhancement == RL2_CONTRAST_ENHANCEMENT_GAMMA)
1247 	    {
1248 		/* Contrast Enhancement */
1249 		*selected = 1;
1250 		return RL2_OK;
1251 	    }
1252       }
1253     if (stl->bandSelection == NULL)
1254 	*selected = 0;
1255     else if (stl->bandSelection->selectionType == RL2_BAND_SELECTION_TRIPLE)
1256 	*selected = 1;
1257     else
1258 	*selected = 0;
1259     return RL2_OK;
1260 }
1261 
1262 RL2_DECLARE int
rl2_get_raster_style_triple_band_selection(rl2RasterStylePtr style,unsigned char * red_band,unsigned char * green_band,unsigned char * blue_band)1263 rl2_get_raster_style_triple_band_selection (rl2RasterStylePtr style,
1264 					    unsigned char *red_band,
1265 					    unsigned char *green_band,
1266 					    unsigned char *blue_band)
1267 {
1268 /* return the RasterStyle TripleBand selection */
1269     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1270     if (stl == NULL)
1271 	return RL2_ERROR;
1272     if (stl->bandSelection == NULL)
1273       {
1274 	  if (stl->contrastEnhancement == RL2_CONTRAST_ENHANCEMENT_NORMALIZE ||
1275 	      stl->contrastEnhancement == RL2_CONTRAST_ENHANCEMENT_HISTOGRAM ||
1276 	      stl->contrastEnhancement == RL2_CONTRAST_ENHANCEMENT_GAMMA)
1277 	    {
1278 		/* Contrast Enhancement */
1279 		*red_band = 0;
1280 		*green_band = 1;
1281 		*blue_band = 2;
1282 		return RL2_OK;
1283 	    }
1284       }
1285     if (stl->bandSelection == NULL)
1286 	return RL2_ERROR;
1287     else if (stl->bandSelection->selectionType == RL2_BAND_SELECTION_TRIPLE)
1288       {
1289 	  *red_band = stl->bandSelection->redBand;
1290 	  *green_band = stl->bandSelection->greenBand;
1291 	  *blue_band = stl->bandSelection->blueBand;
1292 	  return RL2_OK;
1293       }
1294     else
1295 	return RL2_ERROR;
1296 }
1297 
1298 RL2_DECLARE int
rl2_get_raster_style_overall_contrast_enhancement(rl2RasterStylePtr style,unsigned char * contrast_enhancement,double * gamma_value)1299 rl2_get_raster_style_overall_contrast_enhancement (rl2RasterStylePtr style,
1300 						   unsigned char
1301 						   *contrast_enhancement,
1302 						   double *gamma_value)
1303 {
1304 /* return the RasterStyle OverallContrastEnhancement */
1305     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1306     if (stl == NULL)
1307 	return RL2_ERROR;
1308     *contrast_enhancement = stl->contrastEnhancement;
1309     *gamma_value = stl->gammaValue;
1310     return RL2_OK;
1311 }
1312 
1313 RL2_DECLARE int
rl2_get_raster_style_red_band_contrast_enhancement(rl2RasterStylePtr style,unsigned char * contrast_enhancement,double * gamma_value)1314 rl2_get_raster_style_red_band_contrast_enhancement (rl2RasterStylePtr style,
1315 						    unsigned char
1316 						    *contrast_enhancement,
1317 						    double *gamma_value)
1318 {
1319 /* return the RasterStyle RedBand ContrastEnhancement */
1320     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1321     if (stl == NULL)
1322 	return RL2_ERROR;
1323     if (stl->bandSelection == NULL)
1324 	return RL2_ERROR;
1325     else if (stl->bandSelection->selectionType == RL2_BAND_SELECTION_TRIPLE)
1326       {
1327 	  *contrast_enhancement = stl->bandSelection->redContrast;
1328 	  *gamma_value = stl->bandSelection->redGamma;
1329 	  return RL2_OK;
1330       }
1331     return RL2_ERROR;
1332 }
1333 
1334 RL2_DECLARE int
rl2_get_raster_style_green_band_contrast_enhancement(rl2RasterStylePtr style,unsigned char * contrast_enhancement,double * gamma_value)1335 rl2_get_raster_style_green_band_contrast_enhancement (rl2RasterStylePtr style,
1336 						      unsigned char
1337 						      *contrast_enhancement,
1338 						      double *gamma_value)
1339 {
1340 /* return the RasterStyle GreenBand ContrastEnhancement */
1341     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1342     if (stl == NULL)
1343 	return RL2_ERROR;
1344     if (stl->bandSelection == NULL)
1345 	return RL2_ERROR;
1346     else if (stl->bandSelection->selectionType == RL2_BAND_SELECTION_TRIPLE)
1347       {
1348 	  *contrast_enhancement = stl->bandSelection->greenContrast;
1349 	  *gamma_value = stl->bandSelection->greenGamma;
1350 	  return RL2_OK;
1351       }
1352     return RL2_ERROR;
1353 }
1354 
1355 RL2_DECLARE int
rl2_get_raster_style_blue_band_contrast_enhancement(rl2RasterStylePtr style,unsigned char * contrast_enhancement,double * gamma_value)1356 rl2_get_raster_style_blue_band_contrast_enhancement (rl2RasterStylePtr style,
1357 						     unsigned char
1358 						     *contrast_enhancement,
1359 						     double *gamma_value)
1360 {
1361 /* return the RasterStyle BlueBand ContrastEnhancement */
1362     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1363     if (stl == NULL)
1364 	return RL2_ERROR;
1365     if (stl->bandSelection == NULL)
1366 	return RL2_ERROR;
1367     else if (stl->bandSelection->selectionType == RL2_BAND_SELECTION_TRIPLE)
1368       {
1369 	  *contrast_enhancement = stl->bandSelection->blueContrast;
1370 	  *gamma_value = stl->bandSelection->blueGamma;
1371 	  return RL2_OK;
1372       }
1373     return RL2_ERROR;
1374 }
1375 
1376 RL2_DECLARE int
rl2_get_raster_style_gray_band_contrast_enhancement(rl2RasterStylePtr style,unsigned char * contrast_enhancement,double * gamma_value)1377 rl2_get_raster_style_gray_band_contrast_enhancement (rl2RasterStylePtr style,
1378 						     unsigned char
1379 						     *contrast_enhancement,
1380 						     double *gamma_value)
1381 {
1382 /* return the RasterStyle GrayBand ContrastEnhancement */
1383     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1384     if (stl == NULL)
1385 	return RL2_ERROR;
1386     if (stl->bandSelection == NULL)
1387 	return RL2_ERROR;
1388     else if (stl->bandSelection->selectionType == RL2_BAND_SELECTION_MONO)
1389       {
1390 	  *contrast_enhancement = stl->bandSelection->grayContrast;
1391 	  *gamma_value = stl->bandSelection->grayGamma;
1392 	  return RL2_OK;
1393       }
1394     return RL2_ERROR;
1395 }
1396 
1397 RL2_DECLARE int
rl2_has_raster_style_shaded_relief(rl2RasterStylePtr style,int * shaded_relief)1398 rl2_has_raster_style_shaded_relief (rl2RasterStylePtr style, int *shaded_relief)
1399 {
1400 /* return if the RasterStyle has ShadedRelief */
1401     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1402     if (stl == NULL)
1403 	return RL2_ERROR;
1404     *shaded_relief = stl->shadedRelief;
1405     return RL2_OK;
1406 }
1407 
1408 RL2_DECLARE int
rl2_get_raster_style_shaded_relief(rl2RasterStylePtr style,int * brightness_only,double * relief_factor)1409 rl2_get_raster_style_shaded_relief (rl2RasterStylePtr style,
1410 				    int *brightness_only, double *relief_factor)
1411 {
1412 /* return the RasterStyle ShadedRelief parameters */
1413     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1414     if (stl == NULL)
1415 	return RL2_ERROR;
1416     if (stl->shadedRelief)
1417       {
1418 	  *brightness_only = stl->brightnessOnly;
1419 	  *relief_factor = stl->reliefFactor;
1420 	  return RL2_OK;
1421       }
1422     return RL2_ERROR;
1423 }
1424 
1425 RL2_DECLARE int
rl2_has_raster_style_color_map_interpolated(rl2RasterStylePtr style,int * interpolated)1426 rl2_has_raster_style_color_map_interpolated (rl2RasterStylePtr style,
1427 					     int *interpolated)
1428 {
1429 /* return if the RasterStyle has an Interpolated ColorMap */
1430     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1431     if (stl == NULL)
1432 	return RL2_ERROR;
1433     if (stl->interpolate != NULL)
1434 	*interpolated = 1;
1435     else
1436 	*interpolated = 0;
1437     return RL2_OK;
1438 }
1439 
1440 RL2_DECLARE int
rl2_has_raster_style_color_map_categorized(rl2RasterStylePtr style,int * categorized)1441 rl2_has_raster_style_color_map_categorized (rl2RasterStylePtr style,
1442 					    int *categorized)
1443 {
1444 /* return if the RasterStyle has a Categorized ColorMap */
1445     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1446     if (stl == NULL)
1447 	return RL2_ERROR;
1448     if (stl->categorize != NULL)
1449 	*categorized = 1;
1450     else
1451 	*categorized = 0;
1452     return RL2_OK;
1453 }
1454 
1455 RL2_DECLARE int
rl2_get_raster_style_color_map_default(rl2RasterStylePtr style,unsigned char * red,unsigned char * green,unsigned char * blue)1456 rl2_get_raster_style_color_map_default (rl2RasterStylePtr style,
1457 					unsigned char *red,
1458 					unsigned char *green,
1459 					unsigned char *blue)
1460 {
1461 /* return the RasterStyle ColorMap Default color */
1462     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1463     if (stl == NULL)
1464 	return RL2_ERROR;
1465     if (stl->interpolate != NULL)
1466       {
1467 	  *red = stl->interpolate->dfltRed;
1468 	  *green = stl->interpolate->dfltGreen;
1469 	  *blue = stl->interpolate->dfltBlue;
1470 	  return RL2_OK;
1471       }
1472     if (stl->categorize != NULL)
1473       {
1474 	  *red = stl->categorize->dfltRed;
1475 	  *green = stl->categorize->dfltGreen;
1476 	  *blue = stl->categorize->dfltBlue;
1477 	  return RL2_OK;
1478       }
1479     return RL2_ERROR;
1480 }
1481 
1482 RL2_DECLARE int
rl2_get_raster_style_color_map_category_base(rl2RasterStylePtr style,unsigned char * red,unsigned char * green,unsigned char * blue)1483 rl2_get_raster_style_color_map_category_base (rl2RasterStylePtr style,
1484 					      unsigned char *red,
1485 					      unsigned char *green,
1486 					      unsigned char *blue)
1487 {
1488 /* return the RasterStyle ColorMap Category base-color */
1489     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1490     if (stl == NULL)
1491 	return RL2_ERROR;
1492     if (stl->categorize != NULL)
1493       {
1494 	  *red = stl->categorize->baseRed;
1495 	  *green = stl->categorize->baseGreen;
1496 	  *blue = stl->categorize->baseBlue;
1497 	  return RL2_OK;
1498       }
1499     return RL2_ERROR;
1500 }
1501 
1502 RL2_DECLARE int
rl2_get_raster_style_color_map_count(rl2RasterStylePtr style,int * count)1503 rl2_get_raster_style_color_map_count (rl2RasterStylePtr style, int *count)
1504 {
1505 /* return the RasterStyle ColorMap items count */
1506     int cnt;
1507     rl2PrivColorMapPointPtr pt;
1508     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1509     if (stl == NULL)
1510 	return RL2_ERROR;
1511     if (stl->categorize != NULL)
1512       {
1513 	  cnt = 0;
1514 	  pt = stl->categorize->first;
1515 	  while (pt != NULL)
1516 	    {
1517 		cnt++;
1518 		pt = pt->next;
1519 	    }
1520 	  *count = cnt;
1521 	  return RL2_OK;
1522       }
1523     if (stl->interpolate != NULL)
1524       {
1525 	  cnt = 0;
1526 	  pt = stl->interpolate->first;
1527 	  while (pt != NULL)
1528 	    {
1529 		cnt++;
1530 		pt = pt->next;
1531 	    }
1532 	  *count = cnt;
1533 	  return RL2_OK;
1534       }
1535     return RL2_ERROR;
1536 }
1537 
1538 RL2_DECLARE int
rl2_get_raster_style_color_map_entry(rl2RasterStylePtr style,int index,double * value,unsigned char * red,unsigned char * green,unsigned char * blue)1539 rl2_get_raster_style_color_map_entry (rl2RasterStylePtr style, int index,
1540 				      double *value, unsigned char *red,
1541 				      unsigned char *green, unsigned char *blue)
1542 {
1543 /* return the RasterStyle ColorMap item values */
1544     int cnt;
1545     rl2PrivColorMapPointPtr pt;
1546     rl2PrivRasterStylePtr stl = (rl2PrivRasterStylePtr) style;
1547     if (stl == NULL)
1548 	return RL2_ERROR;
1549     if (stl->categorize != NULL)
1550       {
1551 	  cnt = 0;
1552 	  pt = stl->categorize->first;
1553 	  while (pt != NULL)
1554 	    {
1555 		if (index == cnt)
1556 		  {
1557 		      *value = pt->value;
1558 		      *red = pt->red;
1559 		      *green = pt->green;
1560 		      *blue = pt->blue;
1561 		      return RL2_OK;
1562 		  }
1563 		cnt++;
1564 		pt = pt->next;
1565 	    }
1566       }
1567     if (stl->interpolate != NULL)
1568       {
1569 	  cnt = 0;
1570 	  pt = stl->interpolate->first;
1571 	  while (pt != NULL)
1572 	    {
1573 		if (index == cnt)
1574 		  {
1575 		      *value = pt->value;
1576 		      *red = pt->red;
1577 		      *green = pt->green;
1578 		      *blue = pt->blue;
1579 		      return RL2_OK;
1580 		  }
1581 		cnt++;
1582 		pt = pt->next;
1583 	    }
1584       }
1585     return RL2_ERROR;
1586 }
1587 
1588 static void
parse_sld_named_style(xmlNodePtr node,char ** namedStyle)1589 parse_sld_named_style (xmlNodePtr node, char **namedStyle)
1590 {
1591 /* attempting to parse an SLD Named Style */
1592     while (node)
1593       {
1594 	  if (node->type == XML_ELEMENT_NODE)
1595 	    {
1596 		const char *name = (const char *) (node->name);
1597 		if (strcmp (name, "Name") == 0)
1598 		  {
1599 		      xmlNodePtr child = node->children;
1600 		      while (child)
1601 			{
1602 			    if (child->type == XML_TEXT_NODE
1603 				&& child->content != NULL)
1604 			      {
1605 				  int len =
1606 				      (int)
1607 				      strlen ((const char *) (child->content));
1608 				  *namedStyle = malloc (len + 1);
1609 				  strcpy (*namedStyle,
1610 					  (const char *) (child->content));
1611 			      }
1612 			    child = child->next;
1613 			}
1614 		  }
1615 	    }
1616 	  node = node->next;
1617       }
1618 }
1619 
1620 static int
parse_sld_named_layer(xmlNodePtr node,char ** namedLayer,char ** namedStyle)1621 parse_sld_named_layer (xmlNodePtr node, char **namedLayer, char **namedStyle)
1622 {
1623 /* attempting to parse an SLD Named Layer */
1624     int ok = 0;
1625     while (node)
1626       {
1627 	  if (node->type == XML_ELEMENT_NODE)
1628 	    {
1629 		const char *name = (const char *) (node->name);
1630 		if (strcmp (name, "Name") == 0)
1631 		  {
1632 		      xmlNodePtr child = node->children;
1633 		      while (child)
1634 			{
1635 			    if (child->type == XML_TEXT_NODE
1636 				&& child->content != NULL)
1637 			      {
1638 				  int len =
1639 				      (int)
1640 				      strlen ((const char *) (child->content));
1641 				  *namedLayer = malloc (len + 1);
1642 				  strcpy (*namedLayer,
1643 					  (const char *) (child->content));
1644 				  ok = 1;
1645 			      }
1646 			    child = child->next;
1647 			}
1648 		  }
1649 		if (strcmp (name, "NamedStyle") == 0)
1650 		    parse_sld_named_style (node->children, namedStyle);
1651 	    }
1652 	  node = node->next;
1653       }
1654     return ok;
1655 }
1656 
1657 static int
parse_sld(xmlNodePtr node,rl2PrivGroupStylePtr style)1658 parse_sld (xmlNodePtr node, rl2PrivGroupStylePtr style)
1659 {
1660 /* attempting to parse an SLD Style */
1661     int ok = 0;
1662     while (node)
1663       {
1664 	  if (node->type == XML_ELEMENT_NODE)
1665 	    {
1666 		const char *name = (const char *) (node->name);
1667 		if (strcmp (name, "NamedLayer") == 0)
1668 		  {
1669 		      char *namedLayer = NULL;
1670 		      char *namedStyle = NULL;
1671 		      int ret =
1672 			  parse_sld_named_layer (node->children, &namedLayer,
1673 						 &namedStyle);
1674 		      if (ret)
1675 			{
1676 			    rl2PrivChildStylePtr child =
1677 				malloc (sizeof (rl2PrivChildStyle));
1678 			    child->namedLayer = namedLayer;
1679 			    child->namedStyle = namedStyle;
1680 			    child->validLayer = 0;
1681 			    child->validStyle = 0;
1682 			    child->next = NULL;
1683 			    if (style->first == NULL)
1684 				style->first = child;
1685 			    if (style->last != NULL)
1686 				style->last->next = child;
1687 			    style->last = child;
1688 			    ok = 1;
1689 			}
1690 		  }
1691 	    }
1692 	  node = node->next;
1693       }
1694     return ok;
1695 }
1696 
1697 static int
parse_group_style(xmlNodePtr node,rl2PrivGroupStylePtr style)1698 parse_group_style (xmlNodePtr node, rl2PrivGroupStylePtr style)
1699 {
1700 /* parsing an SLD Style */
1701     while (node)
1702       {
1703 	  if (node->type == XML_ELEMENT_NODE)
1704 	    {
1705 		const char *name = (const char *) (node->name);
1706 		if (strcmp (name, "StyledLayerDescriptor") == 0)
1707 		  {
1708 		      int ret = parse_sld (node->children, style);
1709 		      return ret;
1710 		  }
1711 	    }
1712 	  node = node->next;
1713       }
1714     return 0;
1715 }
1716 
1717 RL2_PRIVATE rl2GroupStylePtr
group_style_from_sld_xml(char * name,char * title,char * abstract,unsigned char * xml)1718 group_style_from_sld_xml (char *name, char *title, char *abstract,
1719 			  unsigned char *xml)
1720 {
1721 /* attempting to build a Layer Group Style object from an SLD XML style */
1722     rl2PrivGroupStylePtr style = NULL;
1723     xmlDocPtr xml_doc = NULL;
1724     xmlNodePtr root;
1725     xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) dummySilentError;
1726 
1727     style = malloc (sizeof (rl2PrivGroupStyle));
1728     if (style == NULL)
1729 	return NULL;
1730     style->name = name;
1731     style->title = title;
1732     style->abstract = abstract;
1733     style->first = NULL;
1734     style->last = NULL;
1735     style->valid = 0;
1736 
1737 /* parsing the XML document */
1738     xmlSetGenericErrorFunc (NULL, silentError);
1739     xml_doc =
1740 	xmlReadMemory ((const char *) xml, strlen ((const char *) xml),
1741 		       "noname.xml", NULL, 0);
1742     if (xml_doc == NULL)
1743       {
1744 	  /* parsing error; not a well-formed XML */
1745 	  goto error;
1746       }
1747     root = xmlDocGetRootElement (xml_doc);
1748     if (root == NULL)
1749 	goto error;
1750     if (!parse_group_style (root, style))
1751 	goto error;
1752     xmlFreeDoc (xml_doc);
1753     free (xml);
1754     xml = NULL;
1755 
1756     if (style->name == NULL)
1757 	goto error;
1758 
1759     return (rl2GroupStylePtr) style;
1760 
1761   error:
1762     if (xml != NULL)
1763 	free (xml);
1764     if (xml_doc != NULL)
1765 	xmlFreeDoc (xml_doc);
1766     if (style != NULL)
1767 	rl2_destroy_group_style ((rl2GroupStylePtr) style);
1768     return NULL;
1769 }
1770 
1771 RL2_DECLARE void
rl2_destroy_group_style(rl2GroupStylePtr style)1772 rl2_destroy_group_style (rl2GroupStylePtr style)
1773 {
1774 /* destroying a Group Style object */
1775     rl2PrivChildStylePtr child;
1776     rl2PrivChildStylePtr child_n;
1777     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1778     if (stl == NULL)
1779 	return;
1780 
1781     if (stl->name != NULL)
1782 	free (stl->name);
1783     if (stl->title != NULL)
1784 	free (stl->title);
1785     if (stl->abstract != NULL)
1786 	free (stl->abstract);
1787     child = stl->first;
1788     while (child != NULL)
1789       {
1790 	  child_n = child->next;
1791 	  if (child->namedLayer != NULL)
1792 	      free (child->namedLayer);
1793 	  if (child->namedStyle != NULL)
1794 	      free (child->namedStyle);
1795 	  free (child);
1796 	  child = child_n;
1797       }
1798     free (stl);
1799 }
1800 
1801 RL2_DECLARE const char *
rl2_get_group_style_name(rl2GroupStylePtr style)1802 rl2_get_group_style_name (rl2GroupStylePtr style)
1803 {
1804 /* return the Group Style Name */
1805     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1806     if (stl == NULL)
1807 	return NULL;
1808     return stl->name;
1809 }
1810 
1811 RL2_DECLARE const char *
rl2_get_group_style_title(rl2GroupStylePtr style)1812 rl2_get_group_style_title (rl2GroupStylePtr style)
1813 {
1814 /* return the Group Style Title */
1815     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1816     if (stl == NULL)
1817 	return NULL;
1818     return stl->title;
1819 }
1820 
1821 RL2_DECLARE const char *
rl2_get_group_style_abstract(rl2GroupStylePtr style)1822 rl2_get_group_style_abstract (rl2GroupStylePtr style)
1823 {
1824 /* return the Group Style Abstract */
1825     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1826     if (stl == NULL)
1827 	return NULL;
1828     return stl->abstract;
1829 }
1830 
1831 RL2_DECLARE int
rl2_is_valid_group_style(rl2GroupStylePtr style,int * valid)1832 rl2_is_valid_group_style (rl2GroupStylePtr style, int *valid)
1833 {
1834 /* testing a Group Style for validity */
1835     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1836     if (stl == NULL)
1837 	return RL2_ERROR;
1838     *valid = stl->valid;
1839     return RL2_OK;
1840 }
1841 
1842 RL2_DECLARE int
rl2_get_group_style_count(rl2GroupStylePtr style,int * count)1843 rl2_get_group_style_count (rl2GroupStylePtr style, int *count)
1844 {
1845 /* return the total count of Group Style Items */
1846     int cnt = 0;
1847     rl2PrivChildStylePtr child;
1848     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1849     if (stl == NULL)
1850 	return RL2_ERROR;
1851     child = stl->first;
1852     while (child != NULL)
1853       {
1854 	  /* counting how many Children */
1855 	  cnt++;
1856 	  child = child->next;
1857       }
1858     *count = cnt;
1859     return RL2_OK;
1860 }
1861 
1862 RL2_DECLARE const char *
rl2_get_group_named_layer(rl2GroupStylePtr style,int index)1863 rl2_get_group_named_layer (rl2GroupStylePtr style, int index)
1864 {
1865 /* return the Nth NamedLayer from a Group Style */
1866     int cnt = 0;
1867     const char *str;
1868     rl2PrivChildStylePtr child;
1869     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1870     if (stl == NULL)
1871 	return NULL;
1872     if (index < 0)
1873 	return NULL;
1874     child = stl->first;
1875     while (child != NULL)
1876       {
1877 	  /* counting how many Children */
1878 	  cnt++;
1879 	  child = child->next;
1880       }
1881     if (index >= cnt)
1882 	return NULL;
1883     cnt = 0;
1884     child = stl->first;
1885     while (child != NULL)
1886       {
1887 	  if (cnt == index)
1888 	    {
1889 		str = child->namedLayer;
1890 		break;
1891 	    }
1892 	  cnt++;
1893 	  child = child->next;
1894       }
1895     return str;
1896 }
1897 
1898 RL2_DECLARE const char *
rl2_get_group_named_style(rl2GroupStylePtr style,int index)1899 rl2_get_group_named_style (rl2GroupStylePtr style, int index)
1900 {
1901 /* return the Nth NamedStyle from a Group Style */
1902     int cnt = 0;
1903     const char *str;
1904     rl2PrivChildStylePtr child;
1905     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1906     if (stl == NULL)
1907 	return NULL;
1908     if (index < 0)
1909 	return NULL;
1910     child = stl->first;
1911     while (child != NULL)
1912       {
1913 	  /* counting how many Children */
1914 	  cnt++;
1915 	  child = child->next;
1916       }
1917     if (index >= cnt)
1918 	return NULL;
1919     cnt = 0;
1920     child = stl->first;
1921     while (child != NULL)
1922       {
1923 	  if (cnt == index)
1924 	    {
1925 		str = child->namedStyle;
1926 		break;
1927 	    }
1928 	  cnt++;
1929 	  child = child->next;
1930       }
1931     return str;
1932 }
1933 
1934 RL2_DECLARE int
rl2_is_valid_group_named_layer(rl2GroupStylePtr style,int index,int * valid)1935 rl2_is_valid_group_named_layer (rl2GroupStylePtr style, int index, int *valid)
1936 {
1937 /* testing for validity the Nth NamedLayer from a Group Style */
1938     int cnt = 0;
1939     rl2PrivChildStylePtr child;
1940     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1941     if (stl == NULL)
1942 	return RL2_ERROR;
1943     if (index < 0)
1944 	return RL2_ERROR;
1945     child = stl->first;
1946     while (child != NULL)
1947       {
1948 	  /* counting how many Children */
1949 	  cnt++;
1950 	  child = child->next;
1951       }
1952     if (index >= cnt)
1953 	return RL2_ERROR;
1954     cnt = 0;
1955     child = stl->first;
1956     while (child != NULL)
1957       {
1958 	  if (cnt == index)
1959 	    {
1960 		*valid = child->validLayer;
1961 		break;
1962 	    }
1963 	  cnt++;
1964 	  child = child->next;
1965       }
1966     return RL2_OK;
1967 }
1968 
1969 RL2_DECLARE int
rl2_is_valid_group_named_style(rl2GroupStylePtr style,int index,int * valid)1970 rl2_is_valid_group_named_style (rl2GroupStylePtr style, int index, int *valid)
1971 {
1972 /* testing for validity the Nth NamedStyle from a Group Style */
1973     int cnt = 0;
1974     rl2PrivChildStylePtr child;
1975     rl2PrivGroupStylePtr stl = (rl2PrivGroupStylePtr) style;
1976     if (stl == NULL)
1977 	return RL2_ERROR;
1978     if (index < 0)
1979 	return RL2_ERROR;
1980     child = stl->first;
1981     while (child != NULL)
1982       {
1983 	  /* counting how many Children */
1984 	  cnt++;
1985 	  child = child->next;
1986       }
1987     if (index >= cnt)
1988 	return RL2_ERROR;
1989     cnt = 0;
1990     child = stl->first;
1991     while (child != NULL)
1992       {
1993 	  if (cnt == index)
1994 	    {
1995 		*valid = child->validStyle;
1996 		break;
1997 	    }
1998 	  cnt++;
1999 	  child = child->next;
2000       }
2001     return RL2_OK;
2002 }
2003 
2004 static rl2PrivGroupRendererPtr
rl2_alloc_group_renderer(int count)2005 rl2_alloc_group_renderer (int count)
2006 {
2007 /* creating a GroupRenderer object */
2008     int i;
2009     rl2PrivGroupRendererPtr ptr = NULL;
2010     if (count <= 0)
2011 	return NULL;
2012     ptr = malloc (sizeof (rl2PrivGroupRenderer));
2013     if (ptr == NULL)
2014 	return NULL;
2015     ptr->count = count;
2016     ptr->layers = malloc (sizeof (rl2PrivGroupRendererLayer) * count);
2017     if (ptr->layers == NULL)
2018       {
2019 	  free (ptr);
2020 	  return NULL;
2021       }
2022     for (i = 0; i < count; i++)
2023       {
2024 	  rl2PrivGroupRendererLayerPtr lyr = ptr->layers + i;
2025 	  lyr->layer_type = 0;
2026 	  lyr->layer_name = NULL;
2027 	  lyr->coverage = NULL;
2028 	  lyr->style_name = NULL;
2029 	  lyr->raster_symbolizer = NULL;
2030 	  lyr->raster_stats = NULL;
2031       }
2032     return ptr;
2033 }
2034 
2035 static int
rl2_group_renderer_set_raster(rl2PrivGroupRendererPtr group,int index,const char * layer_name,rl2CoveragePtr coverage,const char * style_name,rl2RasterStylePtr symbolizer,rl2RasterStatisticsPtr stats)2036 rl2_group_renderer_set_raster (rl2PrivGroupRendererPtr group, int index,
2037 			       const char *layer_name, rl2CoveragePtr coverage,
2038 			       const char *style_name,
2039 			       rl2RasterStylePtr symbolizer,
2040 			       rl2RasterStatisticsPtr stats)
2041 {
2042 /* setting up one of the Layers within the Group */
2043     int len;
2044     rl2PrivGroupRendererLayerPtr lyr;
2045     rl2PrivGroupRendererPtr ptr = (rl2PrivGroupRendererPtr) group;
2046     if (ptr == NULL)
2047 	return RL2_ERROR;
2048 
2049     if (index >= 0 && index < ptr->count)
2050 	;
2051     else
2052 	return RL2_ERROR;
2053 
2054     lyr = ptr->layers + index;
2055     lyr->layer_type = RL2_GROUP_RENDERER_RASTER_LAYER;
2056     if (lyr->layer_name != NULL)
2057 	free (lyr->layer_name);
2058     if (layer_name == NULL)
2059 	lyr->layer_name = NULL;
2060     else
2061       {
2062 	  len = strlen (layer_name);
2063 	  lyr->layer_name = malloc (len + 1);
2064 	  strcpy (lyr->layer_name, layer_name);
2065       }
2066     if (lyr->coverage != NULL)
2067 	rl2_destroy_coverage (lyr->coverage);
2068     lyr->coverage = (rl2CoveragePtr) coverage;
2069     if (lyr->style_name != NULL)
2070 	free (lyr->style_name);
2071     if (style_name == NULL)
2072 	lyr->style_name = NULL;
2073     else
2074       {
2075 	  len = strlen (style_name);
2076 	  lyr->style_name = malloc (len + 1);
2077 	  strcpy (lyr->style_name, style_name);
2078       }
2079     if (lyr->raster_symbolizer != NULL)
2080 	rl2_destroy_raster_style ((rl2RasterStylePtr) (lyr->raster_symbolizer));
2081     lyr->raster_symbolizer = (rl2PrivRasterStylePtr) symbolizer;
2082     if (lyr->raster_stats != NULL)
2083 	rl2_destroy_raster_statistics ((rl2RasterStatisticsPtr)
2084 				       (lyr->raster_stats));
2085     lyr->raster_stats = (rl2PrivRasterStatisticsPtr) stats;
2086     return RL2_OK;
2087 
2088 }
2089 
2090 static int
rl2_is_valid_group_renderer(rl2PrivGroupRendererPtr ptr,int * valid)2091 rl2_is_valid_group_renderer (rl2PrivGroupRendererPtr ptr, int *valid)
2092 {
2093 /* testing a GroupRenderer for validity */
2094     int i;
2095     int error = 0;
2096     if (ptr == NULL)
2097 	return RL2_ERROR;
2098 
2099     for (i = 0; i < ptr->count; i++)
2100       {
2101 	  rl2PrivGroupRendererLayerPtr lyr = ptr->layers + i;
2102 	  rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) lyr->coverage;
2103 	  if (lyr->layer_type != RL2_GROUP_RENDERER_RASTER_LAYER)
2104 	      error = 1;
2105 	  if (lyr->layer_name == NULL)
2106 	      error = 1;
2107 	  if (lyr->coverage == NULL)
2108 	      error = 1;
2109 	  else
2110 	    {
2111 		if ((cvg->pixelType == RL2_PIXEL_DATAGRID
2112 		     || cvg->pixelType == RL2_PIXEL_MULTIBAND)
2113 		    && lyr->raster_symbolizer == NULL)
2114 		    error = 1;
2115 	    }
2116 	  if (lyr->style_name == NULL)
2117 	      error = 1;
2118 	  if (lyr->raster_stats == NULL)
2119 	      error = 1;
2120       }
2121     if (error)
2122 	*valid = 0;
2123     else
2124 	*valid = 1;
2125     return RL2_OK;
2126 }
2127 
2128 RL2_DECLARE rl2GroupRendererPtr
rl2_create_group_renderer(sqlite3 * sqlite,rl2GroupStylePtr group_style)2129 rl2_create_group_renderer (sqlite3 * sqlite, rl2GroupStylePtr group_style)
2130 {
2131 /* creating a GroupRenderer object */
2132     rl2PrivGroupRendererPtr group = NULL;
2133     int valid;
2134     int count;
2135     int i;
2136 
2137     if (rl2_is_valid_group_style (group_style, &valid) != RL2_OK)
2138 	goto error;
2139     if (!valid)
2140 	goto error;
2141     if (rl2_get_group_style_count (group_style, &count) != RL2_OK)
2142 	goto error;
2143     group = rl2_alloc_group_renderer (count);
2144     if (group == NULL)
2145 	goto error;
2146     for (i = 0; i < count; i++)
2147       {
2148 	  /* testing individual layers/styles */
2149 	  rl2RasterStylePtr symbolizer = NULL;
2150 	  rl2RasterStatisticsPtr stats = NULL;
2151 	  const char *layer_name = rl2_get_group_named_layer (group_style, i);
2152 	  const char *layer_style = rl2_get_group_named_style (group_style, i);
2153 	  rl2CoveragePtr coverage =
2154 	      rl2_create_coverage_from_dbms (sqlite, layer_name);
2155 	  rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) coverage;
2156 	  if (rl2_is_valid_group_named_layer (group_style, 0, &valid) == RL2_OK)
2157 	    {
2158 		if (valid)
2159 		  {
2160 		      /* validating the style */
2161 		      if (layer_style == NULL)
2162 			  layer_style = "default";
2163 		      if (strcasecmp (layer_style, "default") == 0)
2164 			  ;
2165 		      else
2166 			{
2167 			    /* attempting to get a RasterSymbolizer style */
2168 			    symbolizer =
2169 				rl2_create_raster_style_from_dbms (sqlite,
2170 								   layer_name,
2171 								   layer_style);
2172 			}
2173 		      stats =
2174 			  rl2_create_raster_statistics_from_dbms (sqlite,
2175 								  layer_name);
2176 		  }
2177 		if ((cvg->pixelType == RL2_PIXEL_DATAGRID
2178 		     || cvg->pixelType == RL2_PIXEL_MULTIBAND)
2179 		    && symbolizer == NULL)
2180 		  {
2181 		      /* creating a default RasterStyle */
2182 		      rl2PrivRasterStylePtr symb =
2183 			  malloc (sizeof (rl2PrivRasterStyle));
2184 		      symbolizer = (rl2RasterStylePtr) symb;
2185 		      symb->name = malloc (8);
2186 		      strcpy (symb->name, "default");
2187 		      symb->title = NULL;
2188 		      symb->abstract = NULL;
2189 		      symb->opacity = 1.0;
2190 		      symb->contrastEnhancement = RL2_CONTRAST_ENHANCEMENT_NONE;
2191 		      symb->bandSelection =
2192 			  malloc (sizeof (rl2PrivBandSelection));
2193 		      symb->bandSelection->selectionType =
2194 			  RL2_BAND_SELECTION_MONO;
2195 		      symb->bandSelection->grayBand = 0;
2196 		      symb->bandSelection->grayContrast =
2197 			  RL2_CONTRAST_ENHANCEMENT_NONE;
2198 		      symb->categorize = NULL;
2199 		      symb->interpolate = NULL;
2200 		      symb->shadedRelief = 0;
2201 		  }
2202 	    }
2203 	  rl2_group_renderer_set_raster (group, i, layer_name, coverage,
2204 					 layer_style, symbolizer, stats);
2205       }
2206     if (rl2_is_valid_group_renderer (group, &valid) != RL2_OK)
2207 	goto error;
2208     if (!valid)
2209 	goto error;
2210     return (rl2GroupRendererPtr) group;
2211 
2212   error:
2213     if (group != NULL)
2214 	rl2_destroy_group_renderer ((rl2GroupRendererPtr) group);
2215     return NULL;
2216 }
2217 
2218 RL2_DECLARE void
rl2_destroy_group_renderer(rl2GroupRendererPtr group)2219 rl2_destroy_group_renderer (rl2GroupRendererPtr group)
2220 {
2221 /* memory cleanup - destroying a GroupRenderer object */
2222     int i;
2223     rl2PrivGroupRendererPtr ptr = (rl2PrivGroupRendererPtr) group;
2224     if (ptr == NULL)
2225 	return;
2226     for (i = 0; i < ptr->count; i++)
2227       {
2228 	  rl2PrivGroupRendererLayerPtr lyr = ptr->layers + i;
2229 	  if (lyr->layer_name != NULL)
2230 	      free (lyr->layer_name);
2231 	  if (lyr->coverage != NULL)
2232 	      rl2_destroy_coverage (lyr->coverage);
2233 	  if (lyr->style_name != NULL)
2234 	      free (lyr->style_name);
2235 	  if (lyr->raster_symbolizer != NULL)
2236 	      rl2_destroy_raster_style ((rl2RasterStylePtr)
2237 					(lyr->raster_symbolizer));
2238 	  if (lyr->raster_stats != NULL)
2239 	      rl2_destroy_raster_statistics ((rl2RasterStatisticsPtr)
2240 					     (lyr->raster_stats));
2241       }
2242     free (ptr->layers);
2243     free (ptr);
2244 }
2245