/* This file is part of "psdparse" Copyright (C) 2004-9 Toby Thain, toby@telegraphics.com.au 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 */ #include "psdparse.h" static void desc_class(psd_file_t f, int level, int len, struct dictentry *parent); static void desc_reference(psd_file_t f, int level, int len, struct dictentry *parent); static void desc_list(psd_file_t f, int level, int len, struct dictentry *parent); static void desc_double(psd_file_t f, int level, int len, struct dictentry *parent); static void desc_unitfloat(psd_file_t f, int level, int len, struct dictentry *parent); static void desc_unicodestr(psd_file_t f, int level, int len, struct dictentry *parent); static void desc_enumerated(psd_file_t f, int level, int len, struct dictentry *parent); static void desc_integer(psd_file_t f, int level, int len, struct dictentry *parent); static void desc_boolean(psd_file_t f, int level, int len, struct dictentry *parent); static void desc_alias(psd_file_t f, int level, int len, struct dictentry *parent); extern void desc_pdf(psd_file_t f, int level, int len, struct dictentry *parent); static void ascii_string(psd_file_t f, long count){ fputs(" ", xml); while(count--) fputcxml(fgetc(f), xml); fputs("", xml); } void conv_unicodestr(psd_file_t f, long count){ char *buf = malloc(2*count); if(buf){ size_t n = fread(buf, 2, count, f); #ifdef HAVE_ICONV_H size_t inb, outb; char *inbuf, *outbuf, *utf8; iconv(ic, NULL, &inb, NULL, &outb); // reset iconv state outb = 6*count; // sloppy overestimate of buffer (FIXME) if( (utf8 = malloc(outb)) ){ inbuf = buf; inb = 2*n; outbuf = utf8; if(ic != (iconv_t)-1){ if(iconv(ic, &inbuf, &inb, &outbuf, &outb) != (size_t)-1){ // use CDATA wrap until we can pick through the UTF-8 for & < > ' " and escape them fputs("", xml); }else alwayswarn("conv_unicodestr(): iconv() failed, errno=%u (count=%d)\n", errno, count); } free(utf8); } #endif free(buf); } } static void stringorid(psd_file_t f, int level, char *tag){ long count = get4B(f); fprintf(xml, "%s<%s>", tabs(level), tag); if(count) ascii_string(f, count); else{ fputs(" ", xml); fputsxml(getkey(f), xml); fputs("", xml); } fprintf(xml, " \n", tag); } static void ref_property(psd_file_t f, int level, int len, struct dictentry *parent){ desc_class(f, level, len, parent); stringorid(f, level, "KEY"); } static void ref_enumref(psd_file_t f, int level, int len, struct dictentry *parent){ desc_class(f, level, len, parent); desc_enumerated(f, level, len, parent); } static void ref_offset(psd_file_t f, int level, int len, struct dictentry *parent){ desc_class(f, level, len, parent); desc_integer(f, level, len, parent); } static void desc_class(psd_file_t f, int level, int len, struct dictentry *parent){ desc_unicodestr(f, level, len, parent); stringorid(f, level, "CLASS"); } static void desc_reference(psd_file_t f, int level, int len, struct dictentry *parent){ static struct dictentry refdict[] = { // all functions must be present, for this to parse correctly {0, "prop", "PROPERTY", "Property", ref_property}, {0, "Clss", "CLASS", "Class", desc_class}, {0, "Enmr", "ENUMREF", "Enumerated Reference", ref_enumref}, {0, "rele", "-OFFSET", "Offset", ref_offset}, // '-' prefix means keep tag value on one line {0, "Idnt", "IDENTIFIER", "Identifier", NULL}, // doc is missing?! {0, "indx", "INDEX", "Index", NULL}, // doc is missing?! {0, "name", "NAME", "Name", NULL}, // doc is missing?! {0, NULL, NULL, NULL, NULL} }; long count = get4B(f); while(count-- && findbykey(f, level, refdict, getkey(f), len, 0)) ; } struct dictentry *item(psd_file_t f, int level){ static struct dictentry itemdict[] = { {0, "obj ", "REFERENCE", "Reference", desc_reference}, {0, "Objc", "DESCRIPTOR", "Descriptor", descriptor}, // doc missing?! {0, "list", "LIST", "List", desc_list}, // not documented? {0, "VlLs", "LIST", "List", desc_list}, {0, "doub", "-DOUBLE", "Double", desc_double}, // '-' prefix means keep tag value on one line {0, "UntF", "-UNITFLOAT", "Unit float", desc_unitfloat}, {0, "TEXT", "-STRING", "String", desc_unicodestr}, {0, "enum", "ENUMERATED", "Enumerated", desc_enumerated}, // Enmr? (see v6 rel2) {0, "long", "-INTEGER", "Integer", desc_integer}, {0, "bool", "-BOOLEAN", "Boolean", desc_boolean}, {0, "GlbO", "GLOBALOBJECT", "GlobalObject same as Descriptor", descriptor}, {0, "type", "CLASS", "Class", desc_class}, // doc missing?! - Clss? (see v6 rel2) {0, "GlbC", "CLASS", "Class", desc_class}, // doc missing?! {0, "alis", "-ALIAS", "Alias", desc_alias}, {0, "tdta", "DATA", "Engine Data", desc_pdf}, // undocumented, apparently PDF syntax data {0, NULL, NULL, NULL, NULL} }; char *k; struct dictentry *p; p = findbykey(f, level, itemdict, k = getkey(f), 1, 0); if(!p){ fprintf(stderr, "### item(): unknown key '%s'; file offset %#lx\n", k, (unsigned long)ftell(f)); exit(1); } return p; } static struct dictentry *desc_item(psd_file_t f, int level){ stringorid(f, level, "KEY"); return item(f, level); } static void desc_list(psd_file_t f, int level, int len, struct dictentry *parent){ long count = get4B(f); while(count--) item(f, level); } void descriptor(psd_file_t f, int level, int len, struct dictentry *parent){ long count; desc_class(f, level, len, parent); count = get4B(f); fprintf(xml, "%s\n", tabs(level), count); while(count--) desc_item(f, level); } static void desc_double(psd_file_t f, int level, int len, struct dictentry *parent){ fprintf(xml, "%g", getdoubleB(f)); }; static void desc_unitfloat(psd_file_t f, int level, int len, struct dictentry *parent){ static struct dictentry ufdict[] = { {0, "#Ang", "-ANGLE", "angle: base degrees", desc_double}, {0, "#Rsl", "-DENSITY", "density: base per inch", desc_double}, {0, "#Rlt", "-DISTANCE", "distance: base 72ppi", desc_double}, {0, "#Nne", "-NONE", "none: coerced", desc_double}, {0, "#Prc", "-PERCENT", "percent: tagged unit value", desc_double}, {0, "#Pxl", "-PIXELS", "pixels: tagged unit value", desc_double}, {0, NULL, NULL, NULL, NULL} }; findbykey(f, level, ufdict, getkey(f), 1, 0); // FIXME: check for NULL return } static void desc_unicodestr(psd_file_t f, int level, int len, struct dictentry *parent){ long count = get4B(f); fprintf(xml, "%s", parent->tag[0] == '-' ? " " : tabs(level)); conv_unicodestr(f, count); fprintf(xml, "%c", parent->tag[0] == '-' ? ' ' : '\n'); } static void desc_enumerated(psd_file_t f, int level, int len, struct dictentry *parent){ stringorid(f, level, "TYPE"); stringorid(f, level, "ENUM"); } static void desc_integer(psd_file_t f, int level, int len, struct dictentry *parent){ fprintf(xml, "%ld", get4B(f)); } static void desc_boolean(psd_file_t f, int level, int len, struct dictentry *parent){ fprintf(xml, "%d", fgetc(f)); } static void desc_alias(psd_file_t f, int level, int len, struct dictentry *parent){ psd_bytes_t count = get4B(f); fprintf(xml, " ", (unsigned long)count); fseeko(f, count, SEEK_CUR); // skip over }