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