]> www.wagner.pp.ru Git - oss/fgis.git/blob - dll/fgisPalette.c
*** empty log message ***
[oss/fgis.git] / dll / fgisPalette.c
1 /******************************************************************************
2  * $Id: fgisPalette.c,v 1.2 2003-01-07 10:59:52 dron Exp $
3  *
4  * Project:  fGIS core engine
5  * Purpose:  palette handling
6  *
7  ******************************************************************************
8  *
9  * Copyright (C) 1997, Victor Wagner <vitus@ice.ru>
10  * Copyright (C) 2003, Andrey Kiselev <dron@remotesensing.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2, or (at your option)
15  * any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25  * USA.
26  *****************************************************************************
27  */
28
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <tcl.h>
33 #include "fgis.h"
34
35 /*
36  * Global variables
37  */
38
39 /*
40  *# Default palette array 
41  */
42 static int defarray[]={
43 #include "defpal.h"
44 };
45
46 static PALETTE default_palette=defarray;
47 /*
48  * Creates new palette. Optionally fills from existing palette. If no existing
49  * palette supplied, all colors will be white
50  */
51
52 PALETTE new_palette(PALETTE copy_from) 
53 { PALETTE new_p= (PALETTE)Tcl_Alloc(256*sizeof(int));
54   if (copy_from) {
55     memcpy(new_p,copy_from,256*sizeof(int));
56   } else { 
57     int i,*c;
58     for (i=0,c=new_p;i<256;i++)
59       *(c++)=0xffffff;
60   }
61   return new_p;
62 }
63 /*
64  * Parses string, containing pallette in EPPL7 file format EPPL7 
65  */
66 PALETTE parse_palette(Tcl_Interp *interp,char *string)
67 { PALETTE pal;
68   int index,r,g,b;
69   char *start=string,*end, line[80];
70   pal=new_palette(default_palette);
71   /* ASSIGNMENT INSIDE IF */ 
72   while (( end=strchr(start,'\n'))) {
73     int n=(end-start);
74     if (n==0) continue; /*won't bother with empty lines */
75     if (n>79) n=79;
76     strncpy(line,start,n);
77     start=end+1; 
78     if (sscanf(line,"%d %d %d %d",&index,&r,&g,&b)!=4) { 
79         Tcl_Free((char *)pal); 
80         return NULL;
81     }
82     if (index>255||index<0) 
83         continue;
84     pal[index]=(r*255/1000)<<16|(g*255/1000)<<8|(b*255/1000);
85   } ;
86   return pal;
87 }
88 /*
89  * Returns index entry of palette in form #RRGGBB
90  *
91  */
92
93
94 char *Xcolor_string(PALETTE palette,int index)
95 { int value;
96   static char buffer[24];
97   if(index>=0&&index<255)
98       value=palette[index]; 
99   else 
100       value=palette[255];
101   sprintf(buffer,"#%06x",value);
102   return buffer;
103 }
104 /*
105  * parses RGB specification in form #RRGGBB.
106  * Returns integer value or 0x1000000 in case of error.
107  */
108 int ParseRGB(Tcl_Interp *interp,char *spec)
109 {  int val;char *endptr;
110    val= strtol(spec+1,&endptr,16);
111     if ((*endptr)||(spec[0]!='#')||(strlen(spec)!=7)) { 
112        Tcl_SetResult(interp,"Only #RRGGBB color specification is supported",
113            TCL_STATIC);
114         return 0x1000000;
115     }
116     return val;
117
118 /*
119  * Implements "palette" fgis command.
120  * input - argv[1] subcommand, argv[2] parameter, if required.
121  *   subcommands:
122  *   read filename
123  *   parse string
124  *   copy palettename
125  *   blank
126  * Returns (in interp result) - name of newly created palette
127  * Side effects: defines new Tcl command to handle this palette
128  */
129 EXPORT(int, Fgis_Palette)(ClientData data,Tcl_Interp *interp,int argc,char **argv)
130 { PALETTE pal; 
131   if (argc<2) { 
132        Tcl_SetResult(interp,"Wrong # of args. Should be palette command ?arg?",
133            TCL_STATIC); return TCL_ERROR; 
134   }
135   if (!strcmp(argv[1],"read")) { 
136     Tcl_Channel f; /* no comments */
137     int size; /* return value from Tcl_Read. its size,yes but used just for
138                  error checking */
139     char buf[MAX_PALETTE_SIZE];/* place to hold readed file */
140
141     if (Fgis_CkArgs(interp,argc!=3,argv[0]," read filename")) return TCL_ERROR;
142     f=Tcl_OpenFileChannel(interp,argv[2],"r",0666);
143     if (!f) return TCL_ERROR;
144     size=Tcl_Read(f,buf,MAX_PALETTE_SIZE);
145     Tcl_Close(interp,f); 
146     if (size==-1) {return TCL_ERROR;}
147     if (!(pal=parse_palette(interp,buf))) return TCL_ERROR;
148   } else if (!strcmp(argv[1],"parse")) {
149    if (Fgis_CkArgs(interp,argc!=3,argv[0]," parse string")) return TCL_ERROR;
150    if (!(pal=parse_palette(interp,argv[2]))) {
151      return TCL_ERROR;
152    }
153   } else if (!strcmp(argv[1],"set")) {
154      int listc,i;char **listv;
155      if (Fgis_CkArgs(interp,argc!=3,argv[0]," set list")) return TCL_ERROR;
156      pal=new_palette(default_palette);
157      if (TCL_ERROR==Tcl_SplitList(interp,argv[2],&listc,&listv))
158        return TCL_ERROR;
159      for (i=0;i<listc;i++) {
160        pal[i]=ParseRGB(interp,listv[i]);
161        if (pal[i]==0x1000000) { Tcl_Free((char *)listv);return TCL_ERROR;}
162      }
163      Tcl_Free((char *)listv);
164   } else if (!strcmp(argv[1],"copy")) {
165     PALETTE oldpal; 
166     if (Fgis_CkArgs(interp,argc!=3,argv[0]," copy palettename")) return TCL_ERROR;
167     oldpal=Fgis_GetPalette(interp,argv[2]);
168     if (oldpal==NULL)
169        return TCL_ERROR;
170     pal=new_palette(oldpal);
171   } else if (!strcmp(argv[1],"blank")) {
172     if (Fgis_CkArgs(interp,argc!=2,argv[0]," blank")) return TCL_ERROR;
173     pal=new_palette(NULL);
174   } else { 
175    char buffer[255];
176    sprintf(buffer,"Wrong option %s. Should be one of read parse set blank copy",
177             argv[1]);    
178     Tcl_SetResult(interp,buffer,TCL_VOLATILE);
179     return TCL_ERROR;
180   }
181   return Fgis_CreateObjectCommand(interp,"palette",Fgis_PaletteObj,
182         (ClientData)pal, Fgis_DeletePalette);
183 }
184 /*
185  * Obtain PALETTE pointer from name of command.
186  * Returns NULL in case of error.
187  */
188
189 EXPORT(PALETTE, Fgis_GetPalette)(Tcl_Interp *interp, char *name)
190 {
191     Tcl_CmdInfo info;char buffer[255]="Invalid palette: ";
192     if (!Tcl_GetCommandInfo(interp,name,&info)) return NULL;
193     if (info.proc!=&Fgis_PaletteObj) {
194        strcat(buffer,name);
195        Tcl_SetResult(interp,buffer,TCL_VOLATILE);
196        return NULL;
197     }
198     return (PALETTE)(info.clientData);
199 }
200
201 /*
202  * implements palette object command;
203  * Arguments argv[1]- subcommand argv[i] - parameters
204  * Checks subcommand and calls appropriate function
205  */
206
207 EXPORT(int, Fgis_PaletteObj)(ClientData data,Tcl_Interp *interp,int argc,char **argv)
208 {
209   
210   PALETTE clr=(PALETTE)data;  
211   char buffer[255];
212   int read_only=0;
213   /* default palette supposed to be in readonly memory */
214   read_only=clr==default_palette;
215   /* prepare command name for error message */
216   strcpy(buffer,argv[0]);
217   if (Fgis_CkArgs(interp,argc<2,argv[0]," command ?args?"))
218         return TCL_ERROR;
219   if (!strcmp(argv[1],"print")) {
220     int i;
221     if (Fgis_CkArgs(interp,argc!=2,argv[0]," print"))
222        return TCL_ERROR;
223     for (i=0;i<256;i++) {
224       sprintf(buffer,"%3d %4d %4d %4d\n", i,
225         (clr[i]>>16)*1000/255,
226         ((clr[i]>>8) & 0xFF)*1000/255,
227         (clr[i] & 0xff)*1000/255);
228       Tcl_AppendResult(interp,buffer,NULL);
229     }
230     return TCL_OK;
231   } else
232   if (!strcmp(argv[1],"get")) { 
233      int index;
234      if (Fgis_CkArgs(interp,argc!=3,argv[0],
235                " get index"))
236             return TCL_ERROR;
237      if (Tcl_GetInt(interp,argv[2],&index)==TCL_ERROR) return TCL_ERROR;
238      if (index<0||index>255) {
239         Tcl_SetResult(interp,"#ffffff",TCL_STATIC);
240      } else { 
241         Tcl_SetResult(interp,Xcolor_string(clr,index),TCL_VOLATILE);
242      }
243      return TCL_OK;              
244   }
245   else 
246   if (!strcmp(argv[1],"set")) {
247     int index,RGB;
248        if (read_only) {
249           Tcl_AppendResult(interp,argv[0]," is read only",NULL);
250           return TCL_ERROR;
251        }
252    if (Fgis_CkArgs(interp,argc!=4,argv[0],
253             " set index color"))
254       return TCL_ERROR;
255    if (Tcl_GetInt(interp,argv[2],&index)==TCL_ERROR) return TCL_ERROR; 
256    if (index<0||index>255) { 
257        Tcl_SetResult(interp, "Palette index must be from 0 to 255",
258            TCL_STATIC);
259        return TCL_ERROR;
260    }
261    if ((RGB=ParseRGB(interp,argv[3]))>0xFFFFFF) return TCL_ERROR;
262    clr[index]=RGB;
263    return TCL_OK;
264   }
265   else
266   if (!strcmp(argv[1],"list")) {
267    int i; 
268    if (Fgis_CkArgs(interp,argc!=2,argv[0]," list")) 
269      return TCL_ERROR; 
270    for(i=0;i<256;i++)
271    { Tcl_AppendElement(interp,Xcolor_string(clr,i));
272    }
273    return TCL_OK;
274   }
275   else 
276   if (!strcmp(argv[1],"delete")) {
277    if (Fgis_CkArgs(interp,argc!=2,argv[0]," delete")) return TCL_ERROR;
278    if (read_only) {
279     Tcl_AppendResult(interp,buffer," is read only",NULL);
280     return TCL_ERROR;
281    }
282    Tcl_DeleteCommand(interp,argv[0]);
283    return TCL_OK;
284   }
285   else
286   { Tcl_SetResult(interp,"Wrong option. Should be one of print, get, set, "
287       " list, delete", TCL_STATIC);
288     return TCL_ERROR;
289   } 
290  return TCL_OK;
291 }
292
293 EXPORT(void, Fgis_DeletePalette)(ClientData data)
294 {
295  if (data == default_palette) return;
296  Tcl_Free((char *)data);
297 }