#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gimp-print/gimp-print.h>
#include "gimp-print-internal.h"
#include <gimp-print/gimp-print-intl-internal.h>
#include <math.h>
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <string.h>
#include <stdlib.h>
static stp_list_t *paper_list = NULL;
static void
stpi_paper_freefunc(void *item)
{
stp_papersize_t *paper = (stp_papersize_t *) (item);
STP_SAFE_FREE(paper->name);
STP_SAFE_FREE(paper->text);
STP_SAFE_FREE(paper->comment);
STP_SAFE_FREE(paper);
}
static const char *
stpi_paper_namefunc(const void *item)
{
const stp_papersize_t *paper = (const stp_papersize_t *) (item);
return paper->name;
}
static const char *
stpi_paper_long_namefunc(const void *item)
{
const stp_papersize_t *paper = (const stp_papersize_t *) (item);
return paper->text;
}
static int
stpi_paper_list_init(void)
{
if (paper_list)
stp_list_destroy(paper_list);
paper_list = stp_list_create();
stp_list_set_freefunc(paper_list, stpi_paper_freefunc);
stp_list_set_namefunc(paper_list, stpi_paper_namefunc);
stp_list_set_long_namefunc(paper_list, stpi_paper_long_namefunc);
return 0;
}
static inline void
check_paperlist(void)
{
if (paper_list == NULL)
{
stp_xml_parse_file_named("papers.xml");
if (paper_list == NULL)
{
stp_erprintf("No papers found: is STP_MODULE_PATH correct?\n");
stpi_paper_list_init();
}
}
}
static int
stpi_paper_create(stp_papersize_t *p)
{
stp_list_item_t *paper_item;
if (paper_list == NULL)
{
stpi_paper_list_init();
stp_deprintf(STP_DBG_PAPER,
"stpi_paper_create(): initialising paper_list...\n");
}
paper_item = stp_list_get_start(paper_list);
while (paper_item)
{
const stp_papersize_t *ep =
(const stp_papersize_t *) stp_list_item_get_data(paper_item);
if (ep && !strcmp(p->name, ep->name))
{
stpi_paper_freefunc(p);
return 1;
}
paper_item = stp_list_item_next(paper_item);
}
stp_list_item_create(paper_list, NULL, (void *) p);
return 0;
}
static int
stpi_paper_destroy(stp_papersize_t *p)
{
stp_list_item_t *paper_item;
check_paperlist();
paper_item = stp_list_get_start(paper_list);
while (paper_item)
{
const stp_papersize_t *ep = (const stp_papersize_t *)
stp_list_item_get_data(paper_item);
if (ep && !strcmp(p->name, ep->name))
{
stp_list_item_destroy (paper_list, paper_item);
return 0;
}
paper_item = stp_list_item_next(paper_item);
}
return 1;
}
int
stp_known_papersizes(void)
{
check_paperlist();
return stp_list_get_length(paper_list);
}
const stp_papersize_t *
stp_get_papersize_by_name(const char *name)
{
stp_list_item_t *paper;
check_paperlist();
paper = stp_list_get_item_by_name(paper_list, name);
if (!paper)
return NULL;
else
return (const stp_papersize_t *) stp_list_item_get_data(paper);
}
const stp_papersize_t *
stp_get_papersize_by_index(int idx)
{
stp_list_item_t *paper;
check_paperlist();
paper = stp_list_get_item_by_index(paper_list, idx);
if (!paper)
return NULL;
else
return (const stp_papersize_t *) stp_list_item_get_data(paper);
}
static int
paper_size_mismatch(int l, int w, const stp_papersize_t *val)
{
int hdiff = abs(l - (int) val->height);
int vdiff = abs(w - (int) val->width);
return hdiff + vdiff;
}
const stp_papersize_t *
stp_get_papersize_by_size(int l, int w)
{
int score = INT_MAX;
const stp_papersize_t *ref = NULL;
const stp_papersize_t *val = NULL;
int i;
int sizes = stp_known_papersizes();
for (i = 0; i < sizes; i++)
{
val = stp_get_papersize_by_index(i);
if (val->width == w && val->height == l)
return val;
else
{
int myscore = paper_size_mismatch(l, w, val);
if (myscore < score && myscore < 20)
{
ref = val;
score = myscore;
}
}
}
return ref;
}
void
stp_default_media_size(const stp_vars_t *v,
int *width,
int *height)
{
if (stp_get_page_width(v) > 0 && stp_get_page_height(v) > 0)
{
*width = stp_get_page_width(v);
*height = stp_get_page_height(v);
}
else
{
const char *page_size = stp_get_string_parameter(v, "PageSize");
const stp_papersize_t *papersize = NULL;
if (page_size)
papersize = stp_get_papersize_by_name(page_size);
if (!papersize)
{
*width = 1;
*height = 1;
}
else
{
*width = papersize->width;
*height = papersize->height;
}
if (*width == 0)
*width = 612;
if (*height == 0)
*height = 792;
}
}
static stp_papersize_t *
stp_xml_process_paper(stp_mxml_node_t *paper)
{
stp_mxml_node_t *prop;
const char *stmp;
stp_papersize_t *outpaper;
int
id = 0,
name = 0,
height = 0,
width = 0,
left = 0,
right = 0,
bottom = 0,
top = 0,
unit = 0;
if (stp_get_debug_level() & STP_DBG_XML)
{
stmp = stp_mxmlElementGetAttr(paper, (const char*) "name");
stp_erprintf("stp_xml_process_paper: name: %s\n", stmp);
}
outpaper = stp_zalloc(sizeof(stp_papersize_t));
if (!outpaper)
return NULL;
outpaper->name = stp_strdup(stp_mxmlElementGetAttr(paper, "name"));
outpaper->top = 0;
outpaper->left = 0;
outpaper->bottom = 0;
outpaper->right = 0;
if (outpaper->name)
id = 1;
prop = paper->child;
while(prop)
{
if (prop->type == STP_MXML_ELEMENT)
{
const char *prop_name = prop->value.element.name;
if (!strcmp(prop_name, "description"))
{
outpaper->text = stp_strdup(stp_mxmlElementGetAttr(prop, "value"));
name = 1;
}
if (!strcmp(prop_name, "comment"))
outpaper->comment = stp_strdup(stp_mxmlElementGetAttr(prop, "value"));
if (!strcmp(prop_name, "width"))
{
stmp = stp_mxmlElementGetAttr(prop, "value");
if (stmp)
{
outpaper->width = stp_xmlstrtoul(stmp);
width = 1;
}
}
if (!strcmp(prop_name, "height"))
{
stmp = stp_mxmlElementGetAttr(prop, "value");
if (stmp)
{
outpaper->height = stp_xmlstrtoul(stmp);
height = 1;
}
}
if (!strcmp(prop_name, "left"))
{
stmp = stp_mxmlElementGetAttr(prop, "value");
outpaper->left = stp_xmlstrtoul(stmp);
left = 1;
}
if (!strcmp(prop_name, "right"))
{
stmp = stp_mxmlElementGetAttr(prop, "value");
outpaper->right = stp_xmlstrtoul(stmp);
right = 1;
}
if (!strcmp(prop_name, "bottom"))
{
stmp = stp_mxmlElementGetAttr(prop, "value");
outpaper->bottom = stp_xmlstrtoul(stmp);
bottom = 1;
}
if (!strcmp(prop_name, "top"))
{
stmp = stp_mxmlElementGetAttr(prop, "value");
outpaper->top = stp_xmlstrtoul(stmp);
top = 1;
}
if (!strcmp(prop_name, "unit"))
{
stmp = stp_mxmlElementGetAttr(prop, "value");
if (stmp)
{
if (!strcmp(stmp, "english"))
outpaper->paper_unit = PAPERSIZE_ENGLISH_STANDARD;
else if (!strcmp(stmp, "english-extended"))
outpaper->paper_unit = PAPERSIZE_ENGLISH_EXTENDED;
else if (!strcmp(stmp, "metric"))
outpaper->paper_unit = PAPERSIZE_METRIC_STANDARD;
else if (!strcmp(stmp, "metric-extended"))
outpaper->paper_unit = PAPERSIZE_METRIC_EXTENDED;
else
outpaper->paper_unit = PAPERSIZE_METRIC_EXTENDED;
unit = 1;
}
}
}
prop = prop->next;
}
if (id && name && width && height && unit)
return outpaper;
stp_free(outpaper);
outpaper = NULL;
return NULL;
}
static int
stp_xml_process_paperdef(stp_mxml_node_t *paperdef, const char *file)
{
stp_mxml_node_t *paper;
stp_papersize_t *outpaper;
paper = paperdef->child;
while (paper)
{
if (paper->type == STP_MXML_ELEMENT)
{
const char *paper_name = paper->value.element.name;
if (!strcmp(paper_name, "paper"))
{
outpaper = stp_xml_process_paper(paper);
if (outpaper)
stpi_paper_create(outpaper);
}
}
paper = paper->next;
}
return 1;
}
void
stpi_init_paper(void)
{
stp_register_xml_parser("paperdef", stp_xml_process_paperdef);
}