/* * PDFlow -- version.c * * Copyright (c) 2010 Alberto Cuda * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "version.h" static const struct { const char *s; int v [2]; } versions [] = { { "PDF-1.0", { 1, 0 } }, { "PDF-1.1", { 1, 1 } }, { "PDF-1.2", { 1, 2 } }, { "PDF-1.3", { 1, 3 } }, { "PDF-1.4", { 1, 4 } }, { "PDF-1.5", { 1, 5 } }, { "PDF-1.6", { 1, 6 } }, { "PDF-1.7", { 1, 7 } }, { NULL } }; enum s_status v_validate (struct obj_bstr *vspec, int version [2]) { int i; if (vspec -> size < 4 || memcmp (vspec -> s, "PDF-", 4)) return s_make_indirect (S_CSC_NOT_SUPPORTED, "Does not look like a PDF"); for (i = 0; versions [i].s != NULL; i++) if (obj_string_equal (vspec, versions [i].s)) { memcpy (version, versions [i].v, sizeof (version)); return S_CSC_OK; } return s_make_indirect (S_CSC_NOT_SUPPORTED, "Unsupported PDF file version (%.*s)", vspec -> size, vspec -> s); } const char *v_get_hdr (struct v_selection *sel) { int i; for (i = 0; versions [i].s != NULL; i++) if (versions [i].v [0] == sel -> major && versions [i].v [1] == sel -> minor) return versions [i].s; return NULL; } int v_supported (struct v_pref *pref, int major, int minor) { return !pref -> major || pref -> major > major || (pref -> major == major && pref -> minor >= minor); } void v_upgrade (struct v_selection *sel, int major, int minor) { if (!sel -> major || major > sel -> major || (major == sel -> major && minor > sel -> minor)) { sel -> major = major; sel -> minor = minor; } } static int rank (struct v_pref *pref, struct v_option *opt) { if (!v_supported (pref, opt -> major, opt -> minor)) return 0; if (pref -> text && !opt -> text) return -1; return pref -> speed * opt -> speed + pref -> bspeed * opt -> bspeed + pref -> size * opt -> size; } enum s_status v_add_selection (struct v_selection *sel, struct v_optable *table) { struct v_feature *feat; int ranking, best; int i, r; ranking = -1; best = -1; for (i = 0; table -> options [i].name != NULL; i++) { r = rank (sel -> pref, &table -> options [i]); if (r > ranking) { ranking = r; best = i; } } if (ranking < 0) return s_make_indirect (S_CSC_NOT_SUPPORTED, "No eligible %s option for given constraints", table -> name); feat = malloc (sizeof (struct v_feature)); if (feat == NULL) return S_CSC_OUT_OF_MEMORY; v_upgrade (sel, table -> options [best].major, table -> options [best].minor); feat -> next = sel -> list; sel -> list = feat; feat -> table = table; feat -> value = ((uint8_t *) table -> values) + (best * table -> vsize); return S_CSC_OK; } void v_destroy_selection (struct v_selection *sel) { struct v_feature *feat; while (sel -> list != NULL) { feat = sel -> list; sel -> list = feat -> next; free (feat); } } void *v_get_fval (struct v_selection *sel, struct v_optable *table) { struct v_feature *feat; for (feat = sel -> list; feat != NULL; feat = feat -> next) if (feat -> table == table) return feat -> value; return NULL; }