1 // Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #ifndef __render_parse_h__
22 #define __render_parse_h__
25 #include "render/combine.h"
26 #include "render/invariant.h"
27 #include "render/incremental.h"
28 #include "render/zero.h"
31 * Parse strings describing renderers, and return a renderer satisfying
37 static int strpfix(const char *a
, const char *b
) {
38 return strncmp(a
, b
, strlen(a
));
42 fprintf(stderr
, "\n\n*** Error: unable to allocate memory in render_parse. ***\n\n");
46 static void syntax_error(char *explanation
) {
47 fprintf(stderr
, "\n\n*** Error: Render syntax: %s ***\n\n", explanation
);
51 static filter::filter
*get_SF_atomic(const char *type
) {
54 if (!strcmp("sinc", type
)) {
55 return new filter::sinc();
56 } else if (!strpfix("lanc:", type
)) {
57 if (sscanf(type
+ strlen("lanc:"), "%lf", ¶m
) != 1)
58 syntax_error("Unable to get lanczos diameter.");
59 return new filter::lanczos(param
/2);
60 } else if (!strpfix("triangle:", type
)) {
61 if (sscanf(type
+ strlen("triangle:"), "%lf", ¶m
) != 1)
62 syntax_error("Unable to get triangle diameter.");
63 return new filter::triangle(param
/2);
64 } else if (!strpfix("box:", type
)) {
65 if (sscanf(type
+ strlen("box:"), "%lf", ¶m
) != 1)
66 syntax_error("Unable to get box diameter.");
67 return new filter::box(param
/2);
68 } else if (!strpfix("gauss:", type
)) {
69 if (sscanf(type
+ strlen("gauss:"), "%lf", ¶m
) != 1)
70 syntax_error("Unable to get gauss deviation.");
71 return new filter::gauss(param
);
72 } else if (!strpfix("zero", type
)) {
73 return new filter::zero();
75 fprintf(stderr
, "get_SF_atomic type %s\n", type
);
76 syntax_error("Unable to get filter.");
82 * This line should never be reached; it's included to avoid
83 * 'unreachable' messages emitted by some compilers.
89 static filter::filter
*get_SF(const char *orig_type
) {
90 char *type
= strdup(orig_type
);
94 char *star_index
= (char *) type
;
95 while (*star_index
!= '\0'
96 && *star_index
!= '*')
99 if (*star_index
== '\0') {
101 return get_SF_atomic(orig_type
);
105 filter::filter
*result
= new filter::mult(
107 get_SF(star_index
+ 1));
114 static filter::scaled_filter
*get_SSF(const char *type
) {
115 if (!strpfix("coarse:", type
)) {
116 return new filter::scaled_filter(get_SF(type
+ strlen("coarse:")), 1);
117 } else if (!strpfix("fine:", type
)) {
118 return new filter::scaled_filter(get_SF(type
+ strlen("fine:")), 0);
119 } else if (!strpfix("auto:", type
)) {
120 return new filter::scaled_filter(get_SF(type
+ strlen("auto:")), 2);
122 return new filter::scaled_filter(get_SF(type
), 1);
126 static filter::ssfe
*get_SSFE(const char *type
) {
127 if (!strpfix("ex:", type
)) {
128 return new filter::ssfe(get_SSF(type
+ strlen("ex:")), 1);
129 } else if (!strpfix("nex:", type
)) {
130 return new filter::ssfe(get_SSF(type
+ strlen("nex:")), 0);
132 return new filter::ssfe(get_SSF(type
), 1);
136 static render
*get_invariant(const char *type
) {
140 if (!strpfix("min:", type
)) {
141 i
= new invariant(get_SSFE(type
+ strlen("min:")));
143 } else if (!strpfix("max:", type
)) {
144 i
= new invariant(get_SSFE(type
+ strlen("max:")));
146 } else if (!strpfix("last:", type
)) {
147 i
= new invariant(get_SSFE(type
+ strlen("last:")));
149 } else if (!strpfix("first:", type
)) {
150 i
= new invariant(get_SSFE(type
+ strlen("first:")));
152 } else if (!strpfix("avg:", type
)) {
153 i
= new invariant(get_SSFE(type
+ strlen("avg:")));
155 } else if (!strpfix("avgf:", type
)) {
156 if (sscanf(type
+ strlen("avgf:"), "%lf%n", ¶m
, &offset
) != 1)
157 syntax_error("Unable to get avgf weight criterion.");
158 i
= new invariant(get_SSFE(type
+ strlen("avgf:") + offset
+ strlen(":")));
160 } else if (!strpfix("median:", type
)) {
161 i
= new invariant(get_SSFE(type
+ strlen("median:")));
164 i
= new invariant(get_SSFE(type
));
168 for (int index
= 0; index
< render::render_count(); index
++)
169 if (typeid(*render::render_num(index
)) == typeid(incremental
)
170 && i
->equals(((incremental
*)render::render_num(index
))->get_invariant())) {
172 return (incremental
*)render::render_num(index
);
173 } else if (typeid(*i
->ssfe()->get_scaled_filter()->get_filter()) == typeid(filter::zero
)) {
177 // fprintf(stderr, " new '%s'.\n", type);
179 return new incremental(i
);
182 static render
*get_combination(const char *ptype
, const char *dtype
) {
183 render
*partial
= get_invariant(ptype
);
184 render
*_default
= get(dtype
);
185 for (int index
= 0; index
< render::render_count(); index
++)
186 if (typeid(*render::render_num(index
)) == typeid(combine
)
187 && _default
== ((combine
*)render::render_num(index
))->get_default()
188 && partial
== ((combine
*)render::render_num(index
))->get_partial()) {
189 return render::render_num(index
);
192 // fprintf(stderr, " new '%s,%s'.\n", ptype, dtype);
194 return new combine(_default
, partial
);
197 static render
*get(const char *orig_type
) {
198 char *type
= strdup(orig_type
);
202 char *comma_index
= (char *) type
;
203 while (*comma_index
!= '\0'
204 && *comma_index
!= ',')
207 if (*comma_index
== '\0') {
209 return get_invariant(orig_type
);
213 render
*result
= get_combination(type
, comma_index
+ 1);