1 /* Copyright (C) 2000-2012 by George Williams */
2 /* 2013apr13, added mono + grey Jose Da Silva */
3 /*
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6 
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9 
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13 
14  * The name of the author may not be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16 
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <fontforge-config.h>
30 
31 #include "gimage.h"
32 
pixname(int i,int ncol)33 static char *pixname(int i, int ncol) {
34     static char one[2], two[3];
35     char *usable = "!#$%&'()*+,-./0123456789;:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~ ";
36     static int len=0;
37 
38     if ( len==0 ) len = strlen(usable);
39     if ( ncol<len ) {
40 	one[0]=usable[i];
41 return( one );
42     } else {
43 	two[0] = usable[i/len];
44 	two[1] = usable[i%len];
45 return( two );
46     }
47 }
48 
GImageWriteXpm(GImage * gi,char * filename)49 int GImageWriteXpm(GImage *gi, char *filename) {
50 /* Export an *.xpm image. Return 0 if all done okay */
51     struct _GImage *base = gi->list_len==0?gi->u.image:gi->u.images[0];
52     FILE *file;
53     char stem[256];
54     char *pt,*color_type; uint8 *scanline;
55     int i,j;
56 
57     /* This routine only exports mono or color-indexed type images */
58     if ( base->image_type==it_mono )
59 	color_type = "m";
60     else if ( base->image_type==it_index ) {
61 	color_type = "c";
62 	if ( base->clut->is_grey ) {
63 	    color_type = "g";
64 	    if ( base->clut->clut_len<=4 )
65 		color_type = "g4";
66 	}
67     } else {
68 	fprintf(stderr,"Image must be mono or color-indexed.\n");
69 	return( -1 );
70     }
71 
72     /* get filename stem (255chars max) */
73     if ( (pt=strrchr(filename,'/'))!=NULL )
74 	++pt;
75     else
76 	pt=filename;
77     strncpy(stem,pt,sizeof(stem)); stem[255]='\0';
78     if ( (pt=strrchr(stem,'.'))!=NULL && pt!=stem )
79 	*pt = '\0';
80 
81     if ( (file=fopen(filename,"w"))==NULL ) {
82 	fprintf(stderr,"Can't open \"%s\"\n", filename);
83 	return( -1 );
84     }
85 
86     fprintf(file,"/* XPM */\n" );
87     fprintf(file,"static char *%s[] = {\n",stem);
88     fprintf(file,"/* width height ncolors chars_per_pixel */\n");
89     if ( base->image_type==it_mono )
90 	fprintf(file,"\"%d %d 2 1\"\n", (int) base->width, (int) base->height );
91     else
92 	fprintf(file,"\"%d %d %d %d\"\n", (int) base->width, (int) base->height, base->clut->clut_len,
93 	    base->clut->clut_len>95?2:1 );
94     fprintf(file,"/* colors */\n");
95     if ( base->image_type==it_mono ) {
96 	fprintf(file,"\"%s m #%06x\"\n", pixname(0,2),0);
97 	fprintf(file,"\"%s m #%06x\"\n", pixname(1,2),0xffffff);
98     } else {
99 	for ( i=0; i<base->clut->clut_len; ++i )
100 	    fprintf(file,"\"%s %s #%06x\"\n", pixname(i,base->clut->clut_len),color_type,
101 		(int) base->clut->clut[i]);
102     }
103     fprintf(file,"/* image */\n");
104     for ( i=0; i<base->height; ++i ) {
105 	fprintf(file,"\"" );
106 	scanline = base->data + i*base->bytes_per_line;
107 	if ( base->image_type==it_mono )
108 	    for ( j=0; j<base->width; ++j )
109 		fprintf(file,"%s", pixname((scanline[j>>3]>>(7-(j&7)))&1,2));
110 	else
111 	    for ( j=0; j<base->width; ++j )
112 		fprintf(file,"%s", pixname(*scanline++,base->clut->clut_len));
113 	fprintf(file,"\"%s\n", i==base->height-1?"":"," );
114     }
115     fprintf(file,"};\n" );
116     fflush(file);
117 
118     i=ferror(file);
119     fclose(file);
120     return( i );
121 }
122