bugs: suggest Irani-Peleg take invariants from underlying reference rendering.
[Ale.git] / d2 / render_parse.h
blob9c8e54440e158c41cfeedab6031cdbfda8d041d0
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__
24 #include "render.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
32 * the string.
35 class render_parse {
36 private:
37 static int strpfix(const char *a, const char *b) {
38 return strncmp(a, b, strlen(a));
41 static void nomem() {
42 fprintf(stderr, "\n\n*** Error: unable to allocate memory in render_parse. ***\n\n");
43 exit(1);
46 static void syntax_error(const char *explanation) {
47 fprintf(stderr, "\n\n*** Error: Render syntax: %s ***\n\n", explanation);
48 exit(1);
51 static filter::filter *get_SF_atomic(const char *type) {
52 double param;
54 if (!strcmp("sinc", type)) {
55 return new filter::sinc();
56 } else if (!strpfix("lanc:", type)) {
57 if (sscanf(type + strlen("lanc:"), "%lf", &param) != 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", &param) != 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", &param) != 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", &param) != 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();
74 } else {
75 fprintf(stderr, "get_SF_atomic type %s\n", type);
76 syntax_error("Unable to get filter.");
79 assert (0);
82 * This line should never be reached; it's included to avoid
83 * 'unreachable' messages emitted by some compilers.
86 return NULL;
89 static filter::filter *get_SF(const char *orig_type) {
90 char *type = strdup(orig_type);
91 if (type == NULL)
92 nomem();
94 char *star_index = (char *) type;
95 while (*star_index != '\0'
96 && *star_index != '*')
97 star_index++;
99 if (*star_index == '\0') {
100 free(type);
101 return get_SF_atomic(orig_type);
104 *star_index = '\0';
105 filter::filter *result = new filter::mult(
106 get_SF_atomic(type),
107 get_SF(star_index + 1));
108 *star_index = '*';
109 free(type);
110 return result;
113 public:
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);
121 } else {
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);
131 } else {
132 return new filter::ssfe(get_SSF(type), 1);
136 static render *get_invariant(const char *type) {
137 double param;
138 int offset;
139 invariant *i;
140 if (!strpfix("min:", type)) {
141 i = new invariant(get_SSFE(type + strlen("min:")));
142 i->set_min();
143 } else if (!strpfix("max:", type)) {
144 i = new invariant(get_SSFE(type + strlen("max:")));
145 i->set_max();
146 } else if (!strpfix("last:", type)) {
147 i = new invariant(get_SSFE(type + strlen("last:")));
148 i->set_last();
149 } else if (!strpfix("first:", type)) {
150 i = new invariant(get_SSFE(type + strlen("first:")));
151 i->set_first();
152 } else if (!strpfix("avg:", type)) {
153 i = new invariant(get_SSFE(type + strlen("avg:")));
154 i->set_avg();
155 } else if (!strpfix("avgf:", type)) {
156 if (sscanf(type + strlen("avgf:"), "%lf%n", &param, &offset) != 1)
157 syntax_error("Unable to get avgf weight criterion.");
158 i = new invariant(get_SSFE(type + strlen("avgf:") + offset + strlen(":")));
159 i->set_avgf(param);
160 } else if (!strpfix("median:", type)) {
161 i = new invariant(get_SSFE(type + strlen("median:")));
162 i->set_median();
163 } else {
164 i = new invariant(get_SSFE(type));
165 i->set_avg();
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())) {
171 delete i;
172 return (incremental *)render::render_num(index);
173 } else if (typeid(*i->ssfe()->get_scaled_filter()->get_filter()) == typeid(filter::zero)) {
174 return new zero(i);
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);
199 if (type == NULL)
200 nomem();
202 char *comma_index = (char *) type;
203 while (*comma_index != '\0'
204 && *comma_index != ',')
205 comma_index++;
207 if (*comma_index == '\0') {
208 free(type);
209 return get_invariant(orig_type);
212 *comma_index = '\0';
213 render *result = get_combination(type, comma_index + 1);
214 *comma_index = ',';
216 free(type);
217 return result;
222 #endif