3 * sushivision copyright (C) 2006-2007 Monty <monty@xiph.org>
5 * sushivision is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * sushivision is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with sushivision; see the file COPYING. If not, write to the
17 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <fontconfig/fontconfig.h>
30 #include "sushivision.h"
34 void sv_scale_free(sv_scale_t
*in
){
35 sv_scale_t
*s
= (sv_scale_t
*)in
;
39 if(s
->val_list
)free(s
->val_list
);
41 for(i
=0;i
<s
->vals
;i
++)
42 free(s
->label_list
[i
]);
45 if(s
->legend
)free(s
->legend
);
50 sv_scale_t
*sv_scale_new(char *name
, char *vals
){
52 _sv_token
*decl
= _sv_tokenize_declparam(name
);
53 _sv_token
*list
= _sv_tokenize_valuelist(vals
);
55 // sanity check the tokenization
57 fprintf(stderr
,"sushivision: Unable to parse scale argument \"%s\".\n",name
);
61 fprintf(stderr
,"sushivision: Unable to parse scale argument \"%s\".\n",vals
);
65 sv_scale_t
*s
= calloc(1, sizeof(*s
));
67 s
->val_list
= calloc(s
->vals
,sizeof(*s
->val_list
));
68 s
->label_list
= calloc(s
->vals
,sizeof(*s
->label_list
));
70 for(i
=0;i
<s
->vals
;i
++){
71 s
->label_list
[i
] = strdup(list
->values
[i
]->s
);
72 s
->val_list
[i
] = list
->values
[i
]->v
;
75 s
->legend
=strdup(decl
->label
);
82 sv_scale_t
*sv_scale_copy(sv_scale_t
*in
){
83 sv_scale_t
*s
= calloc(1, sizeof(*s
));
87 s
->val_list
= calloc(s
->vals
,sizeof(*s
->val_list
));
88 s
->label_list
= calloc(s
->vals
,sizeof(*s
->label_list
));
89 s
->legend
= strdup(in
->legend
);
91 for(i
=0;i
<s
->vals
;i
++){
92 s
->val_list
[i
] = in
->val_list
[i
];
93 s
->label_list
[i
] = strdup(in
->label_list
[i
]);
98 /************************* plot and graph scalespaces *********************/
100 double _sv_scalespace_value(_sv_scalespace_t
*s
, double pixel
){
101 double val
= (double)(pixel
-s
->first_pixel
)*s
->neg
/s
->step_pixel
+ s
->first_val
;
102 return val
* s
->expm
;
105 void _sv_scalespace_double(_sv_scalespace_t
*s
){
107 s
->expm
= pow(5,s
->five_exponent
) * pow(2,s
->two_exponent
);
113 double _sv_scalespace_pixel(_sv_scalespace_t
*s
, double val
){
116 val
*= s
->step_pixel
;
118 val
+= s
->first_pixel
;
123 double _sv_scalespace_scaledel(_sv_scalespace_t
*from
, _sv_scalespace_t
*to
){
124 return from
->expm
* to
->step_pixel
* from
->neg
* to
->neg
/ (from
->step_pixel
* to
->expm
);
127 long _sv_scalespace_scalenum(_sv_scalespace_t
*from
, _sv_scalespace_t
*to
){
128 int five
= from
->five_exponent
- to
->five_exponent
;
129 int two
= from
->two_exponent
- to
->two_exponent
;
130 long ret
= to
->step_pixel
;
138 long _sv_scalespace_scaleden(_sv_scalespace_t
*from
, _sv_scalespace_t
*to
){
139 int five
= to
->five_exponent
- from
->five_exponent
;
140 int two
= to
->two_exponent
- from
->two_exponent
;
141 long ret
= from
->step_pixel
;
149 long _sv_scalespace_scaleoff(_sv_scalespace_t
*from
, _sv_scalespace_t
*to
){
150 int fiveF
= from
->five_exponent
- to
->five_exponent
;
151 int twoF
= from
->two_exponent
- to
->two_exponent
;
152 int fiveT
= to
->five_exponent
- from
->five_exponent
;
153 int twoT
= to
->two_exponent
- from
->two_exponent
;
157 while(twoF
-->0) expF
*= 2;
158 while(fiveF
-->0) expF
*= 5;
159 while(twoT
-->0) expT
*= 2;
160 while(fiveT
-->0) expT
*= 5;
162 return (2 * from
->first_val
* from
->step_pixel
* from
->neg
- (2 * from
->first_pixel
+ 1))
163 * expF
* to
->step_pixel
165 - (2 * to
->first_val
* to
->step_pixel
* to
->neg
- (2 * to
->first_pixel
+ 1))
166 * expT
* from
->step_pixel
;
169 long _sv_scalespace_scalebin(_sv_scalespace_t
*from
, _sv_scalespace_t
*to
){
170 int fiveF
= from
->five_exponent
- to
->five_exponent
;
171 int twoF
= from
->two_exponent
- to
->two_exponent
;
172 int fiveT
= to
->five_exponent
- from
->five_exponent
;
173 int twoT
= to
->two_exponent
- from
->two_exponent
;
177 while(twoF
-->0) expF
*= 2;
178 while(fiveF
-->0) expF
*= 5;
179 while(twoT
-->0) expT
*= 2;
180 while(fiveT
-->0) expT
*= 5;
182 return (2 * from
->first_val
* from
->step_pixel
* from
->neg
- (2 * from
->first_pixel
))
183 * expF
* to
->step_pixel
185 - (2 * to
->first_val
* to
->step_pixel
* to
->neg
- (2 * to
->first_pixel
))
186 * expT
* from
->step_pixel
;
189 int _sv_scalespace_mark(_sv_scalespace_t
*s
, int num
){
190 return s
->first_pixel
+ s
->step_pixel
*num
;
193 int _sv_scalespace_decimal_exponent(_sv_scalespace_t
*s
){
194 double val
= s
->two_exponent
*.3 + s
->five_exponent
*.7;
196 return (int)floor(val
);
198 return (int)ceil(val
);
202 double _sv_scalespace_label(_sv_scalespace_t
*s
, int num
, char *buffer
){
203 int pixel
= _sv_scalespace_mark(s
,num
);
204 double val
= _sv_scalespace_value(s
,pixel
);
205 int decimal_exponent
= _sv_scalespace_decimal_exponent(s
);
206 if(decimal_exponent
<0){
207 sprintf(buffer
,"%.*f",-decimal_exponent
,val
);
209 sprintf(buffer
,"%.0f",val
);
214 // name is *not* copied
215 _sv_scalespace_t
_sv_scalespace_linear (double lowpoint
, double highpoint
, int pixels
, int max_spacing
, char *name
){
216 double orange
= fabs(highpoint
- lowpoint
), range
;
217 _sv_scalespace_t ret
;
222 int neg
= (lowpoint
>highpoint
?-1:1);
224 if(pixels
<1)pixels
=1;
226 memset(&ret
,0,sizeof(ret
)); // otherwise packing may do us in!
233 ret
.spacing
= max_spacing
;
235 if(orange
< 1e-30*pixels
){
236 // insufficient to safeguard the int64 first var below all by
237 // itself, but it will keep things on track until later checks
238 orange
= 1e-30 * pixels
;
239 highpoint
= lowpoint
+ orange
;
248 while(rint(pixels
/ range
) < max_spacing
){
253 while(rint(pixels
/ range
) > max_spacing
){
259 if (rint(pixels
/ (range
*.2)) <= max_spacing
){
263 if (rint(pixels
/ (range
*.5)) <= max_spacing
){
268 ret
.two_exponent
= two_place
;
269 ret
.five_exponent
= five_place
;
271 if(pixels
== 0. || range
== 0.)
272 ret
.step_pixel
= max_spacing
;
274 ret
.step_pixel
= rint(pixels
/ range
);
275 ret
.expm
= pow(2,two_place
) * pow(5,five_place
);
277 first
= (long long)(lowpoint
/ret
.expm
);
281 if(LLONG_MAX
* ret
.expm
< highpoint
){
282 lowpoint
+= orange
/2;
284 highpoint
= lowpoint
- orange
;
290 if(LLONG_MAX
* ret
.expm
< lowpoint
){
291 lowpoint
-= orange
/2;
293 highpoint
= lowpoint
+ orange
;
299 while((first
+neg
) * ret
.expm
* neg
<= lowpoint
*neg
)
304 if(LLONG_MIN
* ret
.expm
> lowpoint
){
305 lowpoint
+= orange
/2;
307 highpoint
= lowpoint
- orange
;
313 if(LLONG_MIN
* ret
.expm
> highpoint
){
314 lowpoint
-= orange
/2;
316 highpoint
= lowpoint
+ orange
;
322 while((first
-neg
) * ret
.expm
* neg
> highpoint
*neg
)
325 // make sure the scale display has meaningful sig figs to work with */
326 if( first
*128/128 != first
||
327 first
*16*ret
.expm
== (first
*16+neg
)*ret
.expm
||
328 (first
*16+neg
)*ret
.expm
== (first
*16+neg
*2)*ret
.expm
){
329 lowpoint
-= orange
/(neg
*2);
331 highpoint
= lowpoint
+ neg
*orange
;
336 ret
.first_val
= first
;
338 ret
.first_pixel
= rint((first
- (lowpoint
/ ret
.expm
)) * ret
.step_pixel
);