1/* 2 * "$Id: escp2-channels.c,v 1.91 2010/12/19 02:51:37 rlk Exp $" 3 * 4 * Print plug-in EPSON ESC/P2 driver 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#ifdef HAVE_CONFIG_H 25#include <config.h> 26#endif 27#include <gutenprint/gutenprint.h> 28#include "gutenprint-internal.h" 29#include <gutenprint/gutenprint-intl-internal.h> 30#include "print-escp2.h" 31 32static inkgroup_t *default_black_inkgroup; 33 34static void 35load_subchannel(stp_mxml_node_t *node, stp_mxml_node_t *root, physical_subchannel_t *icl) 36{ 37 const char *name; 38 stp_mxml_node_t *child = node->child; 39 name = stp_mxmlElementGetAttr(node, "color"); 40 if (name) 41 icl->color = stp_xmlstrtol(name); 42 name = stp_mxmlElementGetAttr(node, "subchannel"); 43 if (name) 44 icl->subchannel = stp_xmlstrtol(name); 45 else 46 icl->subchannel = -1; 47 name = stp_mxmlElementGetAttr(node, "headOffset"); 48 if (name) 49 icl->head_offset = stp_xmlstrtol(name); 50 name = stp_mxmlElementGetAttr(node, "name"); 51 if (name) 52 icl->name = stp_strdup(name); 53 name = stp_mxmlElementGetAttr(node, "text"); 54 if (name) 55 icl->text = stp_strdup(name); 56 while (child) 57 { 58 if (child->type == STP_MXML_ELEMENT) 59 { 60 const char *param = child->value.element.name; 61 name = stp_mxmlElementGetAttr(child, "name"); 62 if (name && !strcmp(param, "ChannelDensityParam")) 63 icl->channel_density = stp_strdup(name); 64 else if (name && !strcmp(param, "SubchannelTransitionParam")) 65 icl->subchannel_transition = stp_strdup(name); 66 else if (name && !strcmp(param, "SubchannelValueParam")) 67 icl->subchannel_value = stp_strdup(name); 68 else if (name && !strcmp(param, "SubchannelScaleParam")) 69 icl->subchannel_scale = stp_strdup(name); 70 else if (!strcmp(param, "SplitChannels")) 71 { 72 if (stp_mxmlElementGetAttr(child, "count")) 73 icl->split_channel_count = 74 stp_xmlstrtoul(stp_mxmlElementGetAttr(child, "count")); 75 if (icl->split_channel_count > 0) 76 { 77 char *endptr; 78 int count = 0; 79 stp_mxml_node_t *cchild = child->child; 80 icl->split_channels = 81 stp_zalloc(sizeof(short) * icl->split_channel_count); 82 while (cchild && count < icl->split_channel_count) 83 { 84 if (cchild->type == STP_MXML_TEXT) 85 { 86 unsigned val = 87 strtoul(cchild->value.text.string, &endptr, 0); 88 if (endptr) 89 icl->split_channels[count++] = val; 90 } 91 cchild = cchild->next; 92 } 93 } 94 } 95 } 96 child = child->next; 97 } 98} 99 100static void 101load_channel(stp_mxml_node_t *node, stp_mxml_node_t *root, ink_channel_t *icl) 102{ 103 const char *name; 104 stp_mxml_node_t *child = node->child; 105 int count = 0; 106 while (child) 107 { 108 if (child->type == STP_MXML_ELEMENT && 109 !strcmp(child->value.element.name, "subchannel")) 110 count++; 111 child = child->next; 112 } 113 name = stp_mxmlElementGetAttr(node, "name"); 114 if (name) 115 icl->name = stp_strdup(name); 116 icl->n_subchannels = count; 117 icl->subchannels = stp_zalloc(sizeof(physical_subchannel_t) * count); 118 count = 0; 119 child = node->child; 120 while (child) 121 { 122 if (child->type == STP_MXML_ELEMENT) 123 { 124 if (!strcmp(child->value.element.name, "subchannel")) 125 load_subchannel(child, root, &(icl->subchannels[count++])); 126 else if (!strcmp(child->value.element.name, "HueCurve")) 127 { 128 stp_mxml_node_t *cchild = child->child; 129 stp_curve_t *curve; 130 const char *cref = stp_mxmlElementGetAttr(child, "ref"); 131 if (cref) 132 { 133 cchild = stp_mxmlFindElement(root, root, "curve", "name", 134 cref, STP_MXML_DESCEND); 135 STPI_ASSERT(cchild, NULL); 136 } 137 else 138 { 139 while (cchild && cchild->type != STP_MXML_ELEMENT) 140 cchild = cchild->next; 141 STPI_ASSERT(cchild, NULL); 142 } 143 curve = stp_curve_create_from_xmltree(cchild); 144 icl->hue_curve = curve; 145 } 146 else if (!strcmp(child->value.element.name, "HueCurveParam")) 147 { 148 name = stp_mxmlElementGetAttr(child, "name"); 149 if (name) 150 icl->hue_curve_name = stp_strdup(name); 151 } 152 } 153 child = child->next; 154 } 155} 156 157static void 158load_inkname(stp_mxml_node_t *node, stp_mxml_node_t *root, inkname_t *inl, 159 inklist_t *ikl) 160{ 161 const char *name; 162 stp_mxml_node_t *child = node->child; 163 int channel_count = 0; 164 int aux_channel_count = 0; 165 166 while (child) 167 { 168 if (child->type == STP_MXML_ELEMENT) 169 { 170 if (!strcmp(child->value.element.name, "Channels")) 171 { 172 stp_mxml_node_t *cchild = child->child; 173 while (cchild) 174 { 175 if (cchild->type == STP_MXML_ELEMENT && 176 !strcmp(cchild->value.element.name, "channel")) 177 { 178 name = stp_mxmlElementGetAttr(cchild, "index"); 179 if (name) 180 { 181 unsigned idx = stp_xmlstrtoul(name); 182 if (idx + 1 > channel_count) 183 channel_count = idx + 1; 184 } 185 } 186 cchild = cchild->next; 187 } 188 } 189 else if (!strcmp(child->value.element.name, "AuxChannels")) 190 { 191 stp_mxml_node_t *cchild = child->child; 192 while (cchild) 193 { 194 if (cchild->type == STP_MXML_ELEMENT && 195 !strcmp(cchild->value.element.name, "channel")) 196 { 197 name = stp_mxmlElementGetAttr(cchild, "index"); 198 if (name) 199 { 200 unsigned idx = stp_xmlstrtoul(name); 201 if (idx + 1 > aux_channel_count) 202 aux_channel_count = idx + 1; 203 } 204 } 205 cchild = cchild->next; 206 } 207 } 208 } 209 child = child->next; 210 } 211 inl->channel_count = channel_count; 212 if (channel_count > 0) 213 inl->channels = stp_zalloc(sizeof(ink_channel_t) * channel_count); 214 inl->aux_channel_count = aux_channel_count; 215 if (aux_channel_count > 0) 216 inl->aux_channels = stp_zalloc(sizeof(ink_channel_t) * aux_channel_count); 217 name = stp_mxmlElementGetAttr(node, "name"); 218 if (name) 219 inl->name = stp_strdup(name); 220 name = stp_mxmlElementGetAttr(node, "text"); 221 if (name) 222 inl->text = stp_strdup(name); 223 name = stp_mxmlElementGetAttr(node, "InkID"); 224 if (name) 225 { 226 if (!strcmp(name, "CMYK")) 227 inl->inkset = INKSET_CMYK; 228 else if (!strcmp(name, "CcMmYK")) 229 inl->inkset = INKSET_CcMmYK; 230 else if (!strcmp(name, "CcMmYyK")) 231 inl->inkset = INKSET_CcMmYyK; 232 else if (!strcmp(name, "CcMmYKk")) 233 inl->inkset = INKSET_CcMmYKk; 234 else if (!strcmp(name, "Quadtone")) 235 inl->inkset = INKSET_QUADTONE; 236 else if (!strcmp(name, "Hextone")) 237 inl->inkset = INKSET_HEXTONE; 238 else if (!strcmp(name, "OTHER")) 239 inl->inkset = INKSET_OTHER; 240 else if (!strcmp(name, "Extended")) 241 inl->inkset = INKSET_EXTENDED; 242 } 243 244 channel_count = 0; 245 aux_channel_count = 0; 246 child = node->child; 247 while (child) 248 { 249 if (child->type == STP_MXML_ELEMENT) 250 { 251 if (!strcmp(child->value.element.name, "Channels")) 252 { 253 stp_mxml_node_t *cchild = child->child; 254 while (cchild) 255 { 256 if (cchild->type == STP_MXML_ELEMENT && 257 !strcmp(cchild->value.element.name, "channel")) 258 { 259 name = stp_mxmlElementGetAttr(cchild, "index"); 260 if (name) 261 { 262 unsigned idx = stp_xmlstrtoul(name); 263 load_channel(cchild, root, &(inl->channels[idx])); 264 } 265 } 266 cchild = cchild->next; 267 } 268 } 269 else if (!strcmp(child->value.element.name, "AuxChannels")) 270 { 271 stp_mxml_node_t *cchild = child->child; 272 while (cchild) 273 { 274 if (cchild->type == STP_MXML_ELEMENT && 275 !strcmp(cchild->value.element.name, "channel")) 276 { 277 name = stp_mxmlElementGetAttr(cchild, "index"); 278 if (name) 279 { 280 unsigned idx = stp_xmlstrtoul(name); 281 load_channel(cchild, root, &(inl->aux_channels[idx])); 282 } 283 } 284 cchild = cchild->next; 285 } 286 } 287 else if (!strcmp(child->value.element.name, "initSequence") && 288 child->child && child->child->type == STP_MXML_TEXT) 289 ikl->init_sequence = stp_xmlstrtoraw(child->child->value.text.string); 290 else if (!strcmp(child->value.element.name, "deinitSequence") && 291 child->child && child->child->type == STP_MXML_TEXT) 292 ikl->deinit_sequence = stp_xmlstrtoraw(child->child->value.text.string); 293 } 294 child = child->next; 295 } 296} 297 298static void 299load_shades(stp_mxml_node_t *node, stp_mxml_node_t *root, inklist_t *ikl) 300{ 301 stp_mxml_node_t *child = node->child; 302 int count = 0; 303 304 while (child) 305 { 306 if (child->type == STP_MXML_ELEMENT && 307 !strcmp(child->value.element.name, "shade")) 308 count++; 309 child = child->next; 310 } 311 ikl->n_shades = count; 312 ikl->shades = stp_zalloc(sizeof(shade_t) * count); 313 count = 0; 314 child = node->child; 315 while (child) 316 { 317 if (child->type == STP_MXML_ELEMENT && 318 !strcmp(child->value.element.name, "shade")) 319 { 320 if (stp_mxmlElementGetAttr(child, "count")) 321 { 322 unsigned nshades = 323 stp_xmlstrtoul(stp_mxmlElementGetAttr(child, "count")); 324 ikl->shades[count].n_shades = nshades; 325 if (nshades > 0) 326 { 327 char *endptr; 328 stp_mxml_node_t *cchild = child->child; 329 ikl->shades[count].shades = stp_zalloc(sizeof(double) * nshades); 330 nshades = 0; 331 while (cchild && nshades < ikl->shades[count].n_shades) 332 { 333 if (cchild->type == STP_MXML_TEXT) 334 { 335 double val = 336 strtod(cchild->value.text.string, &endptr); 337 if (endptr) 338 ikl->shades[count].shades[nshades++] = val; 339 } 340 cchild = cchild->next; 341 } 342 } 343 } 344 count++; 345 } 346 child = child->next; 347 } 348} 349 350static void 351load_inklist(stp_mxml_node_t *node, stp_mxml_node_t *root, inklist_t *ikl) 352{ 353 const char *name; 354 stp_mxml_node_t *child = node->child; 355 int count = 0; 356 357 while (child) 358 { 359 if (child->type == STP_MXML_ELEMENT) 360 { 361 if (!strcmp(child->value.element.name, "InkName")) 362 count++; 363 else if (!strcmp(child->value.element.name, "initSequence") && 364 child->child && child->child->type == STP_MXML_TEXT) 365 ikl->init_sequence = stp_xmlstrtoraw(child->child->value.text.string); 366 else if (!strcmp(child->value.element.name, "deinitSequence") && 367 child->child && child->child->type == STP_MXML_TEXT) 368 ikl->deinit_sequence = stp_xmlstrtoraw(child->child->value.text.string); 369 } 370 child = child->next; 371 } 372 name = stp_mxmlElementGetAttr(node, "name"); 373 if (name) 374 ikl->name = stp_strdup(name); 375 name = stp_mxmlElementGetAttr(node, "text"); 376 if (name) 377 ikl->text = stp_strdup(name); 378 ikl->n_inks = count; 379 ikl->inknames = stp_zalloc(sizeof(inkname_t) * count); 380 count = 0; 381 child = node->child; 382 while (child) 383 { 384 if (child->type == STP_MXML_ELEMENT) 385 { 386 if (!strcmp(child->value.element.name, "InkName")) 387 { 388 inkname_t *inl = &(ikl->inknames[count++]); 389 inl->init_sequence = ikl->init_sequence; 390 inl->deinit_sequence = ikl->deinit_sequence; 391 load_inkname(child, root, inl, ikl); 392 } 393 else if (!strcmp(child->value.element.name, "Shades")) 394 load_shades(child, root, ikl); 395 } 396 child = child->next; 397 } 398} 399 400static inkgroup_t * 401load_inkgroup(const char *name) 402{ 403 stp_list_t *dirlist = stpi_data_path(); 404 stp_list_item_t *item; 405 inkgroup_t *igl = NULL; 406 item = stp_list_get_start(dirlist); 407 while (item) 408 { 409 const char *dn = (const char *) stp_list_item_get_data(item); 410 char *ffn = stpi_path_merge(dn, name); 411 stp_mxml_node_t *inkgroup = 412 stp_mxmlLoadFromFile(NULL, ffn, STP_MXML_NO_CALLBACK); 413 stp_free(ffn); 414 if (inkgroup) 415 { 416 int count = 0; 417 stp_mxml_node_t *node = stp_mxmlFindElement(inkgroup, inkgroup, 418 "escp2:InkGroup", NULL, 419 NULL, STP_MXML_DESCEND); 420 if (node) 421 { 422 stp_mxml_node_t *child = node->child; 423 igl = stp_zalloc(sizeof(inkgroup_t)); 424 while (child) 425 { 426 if (child->type == STP_MXML_ELEMENT && 427 !strcmp(child->value.element.name, "InkList")) 428 count++; 429 child = child->next; 430 } 431 igl->n_inklists = count; 432 if (stp_mxmlElementGetAttr(node, "name")) 433 igl->name = stp_strdup(stp_mxmlElementGetAttr(node, "name")); 434 else 435 igl->name = stp_strdup(name); 436 igl->inklists = stp_zalloc(sizeof(inklist_t) * count); 437 child = node->child; 438 count = 0; 439 while (child) 440 { 441 if (child->type == STP_MXML_ELEMENT && 442 !strcmp(child->value.element.name, "InkList")) 443 load_inklist(child, node, &(igl->inklists[count++])); 444 child = child->next; 445 } 446 } 447 stp_mxmlDelete(inkgroup); 448 break; 449 } 450 item = stp_list_item_next(item); 451 } 452 stp_list_destroy(dirlist); 453 return igl; 454} 455 456int 457stp_escp2_load_inkgroup(const stp_vars_t *v, const char *name) 458{ 459 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 460 inkgroup_t *igl = load_inkgroup(name); 461 STPI_ASSERT(igl, v); 462 printdef->inkgroup = igl; 463 return (igl != NULL); 464} 465 466const inkname_t * 467stpi_escp2_get_default_black_inkset(void) 468{ 469 if (! default_black_inkgroup) 470 { 471 default_black_inkgroup = load_inkgroup("escp2/inks/defaultblack.xml"); 472 STPI_ASSERT(default_black_inkgroup && 473 default_black_inkgroup->n_inklists >= 1 && 474 default_black_inkgroup->inklists[0].n_inks >= 1, NULL); 475 } 476 return &(default_black_inkgroup->inklists[0].inknames[0]); 477} 478