1/* 2 * "$Id: print-papers.c,v 1.41 2008/07/13 18:05:16 rlk Exp $" 3 * 4 * Print plug-in driver utility functions for the GIMP. 5 * 6 * Copyright 1997-2000 Michael Sweet (mike@easysw.com) and 7 * Robert Krawitz (rlk@alum.mit.edu) 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 */ 23 24/* 25 * This file must include only standard C header files. The core code must 26 * compile on generic platforms that don't support glib, gimp, gtk, etc. 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include <config.h> 31#endif 32#include <gutenprint/gutenprint.h> 33#include "gutenprint-internal.h" 34#include <gutenprint/gutenprint-intl-internal.h> 35#include <math.h> 36#ifdef HAVE_LIMITS_H 37#include <limits.h> 38#endif 39#include <string.h> 40#include <stdlib.h> 41 42static stp_list_t *paper_list = NULL; 43 44static void 45stpi_paper_freefunc(void *item) 46{ 47 stp_papersize_t *paper = (stp_papersize_t *) (item); 48 STP_SAFE_FREE(paper->name); 49 STP_SAFE_FREE(paper->text); 50 STP_SAFE_FREE(paper->comment); 51 STP_SAFE_FREE(paper); 52} 53 54static const char * 55stpi_paper_namefunc(const void *item) 56{ 57 const stp_papersize_t *paper = (const stp_papersize_t *) (item); 58 return paper->name; 59} 60 61static const char * 62stpi_paper_long_namefunc(const void *item) 63{ 64 const stp_papersize_t *paper = (const stp_papersize_t *) (item); 65 return paper->text; 66} 67 68static int 69stpi_paper_list_init(void) 70{ 71 if (paper_list) 72 stp_list_destroy(paper_list); 73 paper_list = stp_list_create(); 74 stp_list_set_freefunc(paper_list, stpi_paper_freefunc); 75 stp_list_set_namefunc(paper_list, stpi_paper_namefunc); 76 stp_list_set_long_namefunc(paper_list, stpi_paper_long_namefunc); 77 /* stp_list_set_sortfunc(stpi_paper_sortfunc); */ 78 79 return 0; 80} 81 82static inline void 83check_paperlist(void) 84{ 85 if (paper_list == NULL) 86 { 87 stp_xml_parse_file_named("papers.xml"); 88 if (paper_list == NULL) 89 { 90 stp_erprintf("No papers found: is STP_MODULE_PATH correct?\n"); 91 stpi_paper_list_init(); 92 } 93 } 94} 95 96static int 97stpi_paper_create(stp_papersize_t *p) 98{ 99 stp_list_item_t *paper_item; 100 101 if (paper_list == NULL) 102 { 103 stpi_paper_list_init(); 104 stp_deprintf(STP_DBG_PAPER, 105 "stpi_paper_create(): initialising paper_list...\n"); 106 } 107 108 /* Check the paper does not already exist */ 109 paper_item = stp_list_get_start(paper_list); 110 while (paper_item) 111 { 112 const stp_papersize_t *ep = 113 (const stp_papersize_t *) stp_list_item_get_data(paper_item); 114 if (ep && !strcmp(p->name, ep->name)) 115 { 116 stpi_paper_freefunc(p); 117 return 1; 118 } 119 paper_item = stp_list_item_next(paper_item); 120 } 121 122 /* Add paper to list */ 123 stp_list_item_create(paper_list, NULL, (void *) p); 124 125 return 0; 126} 127 128int 129stp_known_papersizes(void) 130{ 131 check_paperlist(); 132 return stp_list_get_length(paper_list); 133} 134 135const stp_papersize_t * 136stp_get_papersize_by_name(const char *name) 137{ 138 stp_list_item_t *paper; 139 140 check_paperlist(); 141 paper = stp_list_get_item_by_name(paper_list, name); 142 if (!paper) 143 return NULL; 144 else 145 return (const stp_papersize_t *) stp_list_item_get_data(paper); 146} 147 148const stp_papersize_t * 149stp_get_papersize_by_index(int idx) 150{ 151 stp_list_item_t *paper; 152 153 check_paperlist(); 154 paper = stp_list_get_item_by_index(paper_list, idx); 155 if (!paper) 156 return NULL; 157 else 158 return (const stp_papersize_t *) stp_list_item_get_data(paper); 159} 160 161static int 162paper_size_mismatch(int l, int w, const stp_papersize_t *val) 163{ 164 int hdiff = abs(l - (int) val->height); 165 int vdiff = abs(w - (int) val->width); 166 return hdiff > vdiff ? hdiff : vdiff; 167} 168 169const stp_papersize_t * 170stp_get_papersize_by_size(int l, int w) 171{ 172 int score = INT_MAX; 173 const stp_papersize_t *ref = NULL; 174 const stp_papersize_t *val = NULL; 175 int i; 176 int sizes = stp_known_papersizes(); 177 for (i = 0; i < sizes; i++) 178 { 179 val = stp_get_papersize_by_index(i); 180 181 if (val->width == w && val->height == l) 182 { 183 if (val->top == 0 && val->left == 0 && 184 val->bottom == 0 && val->right == 0) 185 return val; 186 else 187 ref = val; 188 } 189 else 190 { 191 int myscore = paper_size_mismatch(l, w, val); 192 if (myscore < score && myscore < 5) 193 { 194 ref = val; 195 score = myscore; 196 } 197 } 198 } 199 return ref; 200} 201 202const stp_papersize_t * 203stp_get_papersize_by_size_exact(int l, int w) 204{ 205 const stp_papersize_t *ref = NULL; 206 const stp_papersize_t *val = NULL; 207 int i; 208 int sizes = stp_known_papersizes(); 209 for (i = 0; i < sizes; i++) 210 { 211 val = stp_get_papersize_by_index(i); 212 213 if (val->width == w && val->height == l) 214 { 215 if (val->top == 0 && val->left == 0 && 216 val->bottom == 0 && val->right == 0) 217 return val; 218 else 219 ref = val; 220 } 221 } 222 return ref; 223} 224 225void 226stp_default_media_size(const stp_vars_t *v, /* I */ 227 int *width, /* O - Width in points */ 228 int *height) /* O - Height in points */ 229{ 230 if (stp_get_page_width(v) > 0 && stp_get_page_height(v) > 0) 231 { 232 *width = stp_get_page_width(v); 233 *height = stp_get_page_height(v); 234 } 235 else 236 { 237 const char *page_size = stp_get_string_parameter(v, "PageSize"); 238 const stp_papersize_t *papersize = NULL; 239 if (page_size) 240 papersize = stp_get_papersize_by_name(page_size); 241 if (!papersize) 242 { 243 *width = 1; 244 *height = 1; 245 } 246 else 247 { 248 *width = papersize->width; 249 *height = papersize->height; 250 } 251 if (*width == 0) 252 *width = 612; 253 if (*height == 0) 254 *height = 792; 255 } 256} 257 258/* 259 * Process the <paper> node. 260 */ 261static stp_papersize_t * 262stp_xml_process_paper(stp_mxml_node_t *paper) /* The paper node */ 263{ 264 stp_mxml_node_t *prop; /* Temporary node pointer */ 265 const char *stmp; /* Temporary string */ 266 /* props[] (unused) is the correct tag sequence */ 267 /* const char *props[] = 268 { 269 "name", 270 "description", 271 "width", 272 "height", 273 "left", 274 "right", 275 "bottom", 276 "top", 277 "unit", 278 "type", 279 NULL 280 };*/ 281 stp_papersize_t *outpaper; /* Generated paper */ 282 int 283 id = 0, /* Check id is present */ 284 name = 0, /* Check name is present */ 285 height = 0, /* Check height is present */ 286 width = 0, /* Check width is present */ 287 left = 0, /* Check left is present */ 288 right = 0, /* Check right is present */ 289 bottom = 0, /* Check bottom is present */ 290 top = 0, /* Check top is present */ 291 unit = 0; /* Check unit is present */ 292 293 if (stp_get_debug_level() & STP_DBG_XML) 294 { 295 stmp = stp_mxmlElementGetAttr(paper, (const char*) "name"); 296 stp_erprintf("stp_xml_process_paper: name: %s\n", stmp); 297 } 298 299 outpaper = stp_zalloc(sizeof(stp_papersize_t)); 300 if (!outpaper) 301 return NULL; 302 303 outpaper->name = stp_strdup(stp_mxmlElementGetAttr(paper, "name")); 304 305 outpaper->top = 0; 306 outpaper->left = 0; 307 outpaper->bottom = 0; 308 outpaper->right = 0; 309 outpaper->paper_size_type = PAPERSIZE_TYPE_STANDARD; 310 if (outpaper->name) 311 id = 1; 312 313 prop = paper->child; 314 while(prop) 315 { 316 if (prop->type == STP_MXML_ELEMENT) 317 { 318 const char *prop_name = prop->value.element.name; 319 320 if (!strcmp(prop_name, "description")) 321 { 322 outpaper->text = stp_strdup(stp_mxmlElementGetAttr(prop, "value")); 323 name = 1; 324 } 325 if (!strcmp(prop_name, "comment")) 326 outpaper->comment = stp_strdup(stp_mxmlElementGetAttr(prop, "value")); 327 if (!strcmp(prop_name, "width")) 328 { 329 stmp = stp_mxmlElementGetAttr(prop, "value"); 330 if (stmp) 331 { 332 outpaper->width = stp_xmlstrtoul(stmp); 333 width = 1; 334 } 335 } 336 if (!strcmp(prop_name, "height")) 337 { 338 stmp = stp_mxmlElementGetAttr(prop, "value"); 339 if (stmp) 340 { 341 outpaper->height = stp_xmlstrtoul(stmp); 342 height = 1; 343 } 344 } 345 if (!strcmp(prop_name, "left")) 346 { 347 stmp = stp_mxmlElementGetAttr(prop, "value"); 348 outpaper->left = stp_xmlstrtoul(stmp); 349 left = 1; 350 } 351 if (!strcmp(prop_name, "right")) 352 { 353 stmp = stp_mxmlElementGetAttr(prop, "value"); 354 outpaper->right = stp_xmlstrtoul(stmp); 355 right = 1; 356 } 357 if (!strcmp(prop_name, "bottom")) 358 { 359 stmp = stp_mxmlElementGetAttr(prop, "value"); 360 outpaper->bottom = stp_xmlstrtoul(stmp); 361 bottom = 1; 362 } 363 if (!strcmp(prop_name, "top")) 364 { 365 stmp = stp_mxmlElementGetAttr(prop, "value"); 366 outpaper->top = stp_xmlstrtoul(stmp); 367 top = 1; 368 } 369 if (!strcmp(prop_name, "unit")) 370 { 371 stmp = stp_mxmlElementGetAttr(prop, "value"); 372 if (stmp) 373 { 374 if (!strcmp(stmp, "english")) 375 outpaper->paper_unit = PAPERSIZE_ENGLISH_STANDARD; 376 else if (!strcmp(stmp, "english-extended")) 377 outpaper->paper_unit = PAPERSIZE_ENGLISH_EXTENDED; 378 else if (!strcmp(stmp, "metric")) 379 outpaper->paper_unit = PAPERSIZE_METRIC_STANDARD; 380 else if (!strcmp(stmp, "metric-extended")) 381 outpaper->paper_unit = PAPERSIZE_METRIC_EXTENDED; 382 /* Default unit */ 383 else 384 outpaper->paper_unit = PAPERSIZE_METRIC_EXTENDED; 385 unit = 1; 386 } 387 } 388 if (!strcmp(prop_name, "type")) 389 { 390 stmp = stp_mxmlElementGetAttr(prop, "value"); 391 if (stmp) 392 { 393 if (!strcmp(stmp, "envelope")) 394 outpaper->paper_size_type = PAPERSIZE_TYPE_ENVELOPE; 395 else 396 outpaper->paper_size_type = PAPERSIZE_TYPE_STANDARD; 397 } 398 } 399 } 400 prop = prop->next; 401 } 402 if (id && name && width && height && unit) /* Margins and type are optional */ 403 return outpaper; 404 stp_free(outpaper); 405 outpaper = NULL; 406 return NULL; 407} 408 409/* 410 * Parse the <paperdef> node. 411 */ 412static int 413stp_xml_process_paperdef(stp_mxml_node_t *paperdef, const char *file) /* The paperdef node */ 414{ 415 stp_mxml_node_t *paper; /* paper node pointer */ 416 stp_papersize_t *outpaper; /* Generated paper */ 417 418 paper = paperdef->child; 419 while (paper) 420 { 421 if (paper->type == STP_MXML_ELEMENT) 422 { 423 const char *paper_name = paper->value.element.name; 424 if (!strcmp(paper_name, "paper")) 425 { 426 outpaper = stp_xml_process_paper(paper); 427 if (outpaper) 428 stpi_paper_create(outpaper); 429 } 430 } 431 paper = paper->next; 432 } 433 return 1; 434} 435 436void 437stpi_init_paper(void) 438{ 439 stp_register_xml_parser("paperdef", stp_xml_process_paperdef); 440} 441