]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/filter.c
Merge changes from CUPS 1.5svn-r9049 (private header support)
[thirdparty/cups.git] / scheduler / filter.c
CommitLineData
ef416fc2 1/*
75bd9771 2 * "$Id: filter.c 7694 2008-06-26 00:23:20Z mike $"
ef416fc2 3 *
71e16022 4 * File type conversion routines for CUPS.
ef416fc2 5 *
71e16022 6 * Copyright 2007-2010 by Apple Inc.
f7deaa1a 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
15 * Contents:
16 *
f7deaa1a 17 * mimeAddFilter() - Add a filter to the current MIME database.
18 * mimeFilter() - Find the fastest way to convert from one type to
19 * another.
20 * mimeFilterLookup() - Lookup a filter...
21 * compare_filters() - Compare two filters...
22 * find_filters() - Find the filters to convert from one type to another.
ef416fc2 23 */
24
25/*
26 * Include necessary headers...
27 */
28
71e16022
MS
29#include <cups/string-private.h>
30#include <cups/debug-private.h>
ef416fc2 31#include "mime.h"
32
33
bd7854cb 34/*
35 * Local types...
36 */
37
38typedef struct _mime_typelist_s /**** List of source types ****/
39{
40 struct _mime_typelist_s *next; /* Next source type */
41 mime_type_t *src; /* Source type */
42} _mime_typelist_t;
43
44
ef416fc2 45/*
46 * Local functions...
47 */
48
fa73b229 49static int compare_filters(mime_filter_t *, mime_filter_t *);
a74454a7 50static int compare_srcs(mime_filter_t *, mime_filter_t *);
bd7854cb 51static cups_array_t *find_filters(mime_t *mime, mime_type_t *src,
52 mime_type_t *dst, int *cost,
53 _mime_typelist_t *visited);
ef416fc2 54
55
56/*
57 * 'mimeAddFilter()' - Add a filter to the current MIME database.
58 */
59
60mime_filter_t * /* O - New filter */
61mimeAddFilter(mime_t *mime, /* I - MIME database */
62 mime_type_t *src, /* I - Source type */
63 mime_type_t *dst, /* I - Destination type */
64 int cost, /* I - Relative time/resource cost */
65 const char *filter) /* I - Filter program to run */
66{
67 mime_filter_t *temp; /* New filter */
68
69
70 /*
71 * Range-check the input...
72 */
73
fa73b229 74 if (!mime || !src || !dst || !filter)
ef416fc2 75 return (NULL);
76
77 /*
78 * See if we already have an existing filter for the given source and
79 * destination...
80 */
81
f7deaa1a 82 if ((temp = mimeFilterLookup(mime, src, dst)) != NULL)
ef416fc2 83 {
84 /*
85 * Yup, does the existing filter have a higher cost? If so, copy the
86 * filter and cost to the existing filter entry and return it...
87 */
88
89 if (temp->cost > cost)
90 {
91 temp->cost = cost;
92 strlcpy(temp->filter, filter, sizeof(temp->filter));
93 }
94 }
95 else
96 {
97 /*
98 * Nope, add a new one...
99 */
100
fa73b229 101 if (!mime->filters)
102 mime->filters = cupsArrayNew((cups_array_func_t)compare_filters, NULL);
ef416fc2 103
fa73b229 104 if (!mime->filters)
ef416fc2 105 return (NULL);
106
fa73b229 107 if ((temp = calloc(1, sizeof(mime_filter_t))) == NULL)
108 return (NULL);
ef416fc2 109
110 /*
111 * Copy the information over and sort if necessary...
112 */
113
114 temp->src = src;
115 temp->dst = dst;
116 temp->cost = cost;
117 strlcpy(temp->filter, filter, sizeof(temp->filter));
118
fa73b229 119 cupsArrayAdd(mime->filters, temp);
ef416fc2 120 }
121
122 /*
123 * Return the new/updated filter...
124 */
125
126 return (temp);
127}
128
129
130/*
131 * 'mimeFilter()' - Find the fastest way to convert from one type to another.
132 */
133
fa73b229 134cups_array_t * /* O - Array of filters to run */
ef416fc2 135mimeFilter(mime_t *mime, /* I - MIME database */
136 mime_type_t *src, /* I - Source file type */
137 mime_type_t *dst, /* I - Destination file type */
bd7854cb 138 int *cost) /* O - Cost of filters */
ef416fc2 139{
ef416fc2 140 /*
141 * Range-check the input...
142 */
143
fa73b229 144 DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
bd7854cb 145 "cost=%p(%d))\n",
ef416fc2 146 mime, src, src ? src->super : "?", src ? src->type : "?",
147 dst, dst ? dst->super : "?", dst ? dst->type : "?",
bd7854cb 148 cost, cost ? *cost : 0));
149
ef416fc2 150
fa73b229 151 if (cost)
152 *cost = 0;
ef416fc2 153
bd7854cb 154 if (!mime || !src || !dst)
fa73b229 155 return (NULL);
ef416fc2 156
a74454a7 157 /*
158 * (Re)build the source lookup array as needed...
159 */
160
161 if (!mime->srcs)
162 {
163 mime_filter_t *current; /* Current filter */
164
165
166 mime->srcs = cupsArrayNew((cups_array_func_t)compare_srcs, NULL);
167
168 for (current = mimeFirstFilter(mime);
169 current;
170 current = mimeNextFilter(mime))
171 cupsArrayAdd(mime->srcs, current);
172 }
173
bd7854cb 174 /*
175 * Find the filters...
176 */
177
178 return (find_filters(mime, src, dst, cost, NULL));
179}
180
181
f7deaa1a 182/*
183 * 'mimeFilterLookup()' - Lookup a filter...
184 */
185
186mime_filter_t * /* O - Filter for src->dst */
187mimeFilterLookup(mime_t *mime, /* I - MIME database */
188 mime_type_t *src, /* I - Source type */
189 mime_type_t *dst) /* I - Destination type */
190{
191 mime_filter_t key; /* Key record for filter search */
192
193
194 key.src = src;
195 key.dst = dst;
196
197 return ((mime_filter_t *)cupsArrayFind(mime->filters, &key));
198}
199
200
bd7854cb 201/*
202 * 'compare_filters()' - Compare two filters...
203 */
204
205static int /* O - Comparison result */
206compare_filters(mime_filter_t *f0, /* I - First filter */
207 mime_filter_t *f1) /* I - Second filter */
208{
209 int i; /* Result of comparison */
210
211
212 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
213 if ((i = strcmp(f0->src->type, f1->src->type)) == 0)
214 if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0)
215 i = strcmp(f0->dst->type, f1->dst->type);
216
217 return (i);
218}
219
220
a74454a7 221/*
222 * 'compare_srcs()' - Compare two srcs...
223 */
224
225static int /* O - Comparison result */
226compare_srcs(mime_filter_t *f0, /* I - First filter */
227 mime_filter_t *f1) /* I - Second filter */
228{
229 int i; /* Result of comparison */
230
231
232 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
233 i = strcmp(f0->src->type, f1->src->type);
234
235 return (i);
236}
237
238
bd7854cb 239/*
240 * 'find_filters()' - Find the filters to convert from one type to another.
241 */
242
b423cd4c 243static cups_array_t * /* O - Array of filters to run */
bd7854cb 244find_filters(mime_t *mime, /* I - MIME database */
245 mime_type_t *src, /* I - Source file type */
246 mime_type_t *dst, /* I - Destination file type */
247 int *cost, /* O - Cost of filters */
248 _mime_typelist_t *list) /* I - Source types we've used */
249{
250 int tempcost, /* Temporary cost */
251 mincost; /* Current minimum */
252 cups_array_t *temp, /* Temporary filter */
253 *mintemp; /* Current minimum */
a74454a7 254 mime_filter_t *current, /* Current filter */
255 srckey; /* Source type key */
bd7854cb 256 _mime_typelist_t listnode, /* New list node */
257 *listptr; /* Pointer in list */
258
259
260 DEBUG_printf(("find_filters(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
261 "cost=%p, list=%p)\n", mime, src, src->super, src->type,
262 dst, dst->super, dst->type, cost, list));
263
ef416fc2 264 /*
265 * See if there is a filter that can convert the files directly...
266 */
267
f7deaa1a 268 if ((current = mimeFilterLookup(mime, src, dst)) != NULL)
ef416fc2 269 {
270 /*
271 * Got a direct filter!
272 */
273
ae71f5de 274 DEBUG_puts("find_filters: Direct filter found!");
bd7854cb 275
fa73b229 276 if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL)
ef416fc2 277 return (NULL);
278
fa73b229 279 cupsArrayAdd(mintemp, current);
280
281 mincost = current->cost;
ef416fc2 282
a74454a7 283 if (!cost)
284 return (mintemp);
285
ae71f5de
MS
286 DEBUG_puts("find_filters: Found direct filter:");
287 DEBUG_printf(("find_filters: %s (cost=%d)\n", current->filter, mincost));
ef416fc2 288 }
289 else
290 {
291 /*
292 * No direct filter...
293 */
294
fa73b229 295 mintemp = NULL;
296 mincost = 9999999;
ef416fc2 297 }
298
bd7854cb 299 /*
300 * Initialize this node in the type list...
301 */
302
303 listnode.next = list;
304
ef416fc2 305 /*
306 * OK, now look for filters from the source type to any other type...
307 */
308
a74454a7 309 srckey.src = src;
bd7854cb 310
a74454a7 311 for (current = (mime_filter_t *)cupsArrayFind(mime->srcs, &srckey);
312 current && current->src == src;
313 current = (mime_filter_t *)cupsArrayNext(mime->srcs))
314 {
315 /*
316 * See if we have already tried the destination type as a source
317 * type (this avoids extra filter looping...)
318 */
bd7854cb 319
a74454a7 320 mime_type_t *current_dst; /* Current destination type */
bd7854cb 321
ef416fc2 322
a74454a7 323 for (listptr = list, current_dst = current->dst;
324 listptr;
325 listptr = listptr->next)
326 if (current_dst == listptr->src)
327 break;
328
329 if (listptr)
330 continue;
bd7854cb 331
a74454a7 332 /*
333 * See if we have any filters that can convert from the destination type
334 * of this filter to the final type...
335 */
336
337 listnode.src = current->src;
fa73b229 338
a74454a7 339 cupsArraySave(mime->srcs);
340 temp = find_filters(mime, current->dst, dst, &tempcost, &listnode);
341 cupsArrayRestore(mime->srcs);
342
343 if (!temp)
344 continue;
345
346 if (!cost)
347 return (temp);
348
349 /*
350 * Found a match; see if this one is less costly than the last (if
351 * any...)
352 */
353
ed486911 354 tempcost += current->cost;
355
a74454a7 356 if (tempcost < mincost)
357 {
358 cupsArrayDelete(mintemp);
ef416fc2 359
360 /*
a74454a7 361 * Hey, we got a match! Add the current filter to the beginning of the
362 * filter list...
ef416fc2 363 */
364
a74454a7 365 mintemp = temp;
ed486911 366 mincost = tempcost;
a74454a7 367 cupsArrayInsert(mintemp, current);
ef416fc2 368 }
a74454a7 369 else
370 cupsArrayDelete(temp);
371 }
ef416fc2 372
fa73b229 373 if (mintemp)
ef416fc2 374 {
375 /*
376 * Hey, we got a match!
377 */
378
ef416fc2 379#ifdef DEBUG
ae71f5de
MS
380 DEBUG_printf(("find_filters: Returning %d filters:\n",
381 cupsArrayCount(mintemp)));
382
fa73b229 383 for (current = (mime_filter_t *)cupsArrayFirst(mintemp);
384 current;
385 current = (mime_filter_t *)cupsArrayNext(mintemp))
ae71f5de 386 DEBUG_printf(("find_filters: %s\n", current->filter));
ef416fc2 387#endif /* DEBUG */
388
bd7854cb 389 if (cost)
390 *cost = mincost;
fa73b229 391
ef416fc2 392 return (mintemp);
393 }
394
ae71f5de 395 DEBUG_puts("find_filters: Returning zippo...");
ef416fc2 396
397 return (NULL);
398}
399
400
ef416fc2 401/*
75bd9771 402 * End of "$Id: filter.c 7694 2008-06-26 00:23:20Z mike $".
ef416fc2 403 */