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