1 /*
2  * FIG : Facility for Interactive Generation of figures
3  * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4  * Parts Copyright (c) 1989-2015 by Brian V. Smith
5  * Parts Copyright (c) 1991 by Paul King
6  * Parts Copyright (c) 2016-2020 by Thomas Loimer
7  *
8  * Any party obtaining a copy of these files is granted, free of charge, a
9  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
10  * nonexclusive right and license to deal in this software and documentation
11  * files (the "Software"), including without limitation the rights to use,
12  * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
13  * the Software, and to permit persons who receive copies from any such
14  * party to do so, with the only requirement being that the above copyright
15  * and this permission notice remain intact.
16  *
17  */
18 
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"		/* restrict */
22 #endif
23 
24 #include <stdlib.h>
25 
26 #include <X11/X.h>		/* None */
27 #include <X11/Xlib.h>		/* XColor, XParseColor */
28 #include <X11/xpm.h>
29 
30 #include "resources.h"
31 #include "object.h"
32 #include "f_picobj.h"
33 #include "f_util.h"
34 #include "w_color.h"
35 #include "w_msgpanel.h"
36 #include "w_setup.h"
37 
38 /* attempt to read a XPM (color pixmap) file */
39 /* the filename is passed since XpmReadFileToXpmImage needs a name
40    instead of a FILE pointer.  This is fine because it handles compressed files */
41 
42 /* return codes:  PicSuccess (1) : success
43 		  FileInvalid (-2) : invalid file
44 */
45 
46 int
read_xpm(F_pic * pic,struct xfig_stream * restrict pic_stream)47 read_xpm(F_pic *pic, struct xfig_stream *restrict pic_stream)
48 {
49 	int		status;
50 	XpmImage	image;
51 	unsigned int	i;
52 	char		*c;
53 	XColor		exact_def;
54 
55 	/* make scale factor smaller for metric */
56 	float scale = (appres.INCHES ?
57 			(float)PIX_PER_INCH :
58 			2.54*PIX_PER_CM)/(float)DISPLAY_PIX_PER_INCH;
59 
60 	if (uncompressed_content(pic_stream))
61 		return FileInvalid;
62 
63 	status = XpmReadFileToXpmImage(pic_stream->content, &image, NULL);
64 	/* if out of colors, try switching colormaps and reading again */
65 	if (status == XpmColorFailed) {
66 		if (!switch_colormap())
67 			return PicSuccess;
68 		status = XpmReadFileToXpmImage(pic_stream->content, &image,
69 						NULL);
70 	}
71 	if (status == XpmSuccess) {
72 		/* now look up the colors in the image and put them
73 		   in the pic colormap */
74 		for (i = 0; i < image.ncolors; ++i) {
75 			c = (image.colorTable + i)->c_color;
76 			if (c == NULL || *c == '\0') {
77 				/* use white for null color */
78 				c = "white";
79 				file_msg("white used for *NULL color");
80 			}
81 			if (XParseColor(tool_d, tool_cm, c, &exact_def) == 0) {
82 				file_msg("Error parsing color %s",c);
83 				exact_def.red = exact_def.green =
84 					exact_def.blue = 65535;
85 			}
86 			pic->pic_cache->cmap[i].red = exact_def.red >> 8;
87 			pic->pic_cache->cmap[i].green = exact_def.green >> 8;
88 			pic->pic_cache->cmap[i].blue = exact_def.blue >> 8;
89 		}
90 		pic->pic_cache->subtype = T_PIC_XPM;
91 		pic->pic_cache->numcols = image.ncolors;
92 		pic->pixmap = None;
93 		pic->pic_cache->bitmap = malloc(image.width * image.height *
94 				sizeof(unsigned char));
95 		if (pic->pic_cache->bitmap == NULL) {
96 			file_msg("cannot allocate space for XPM image");
97 			return PicSuccess;
98 		}
99 		for (i=0; i<image.width*image.height; i++)
100 			pic->pic_cache->bitmap[i] =(unsigned char)image.data[i];
101 		pic->hw_ratio = (float)image.height / image.width;
102 		pic->pic_cache->bit_size.x = image.width;
103 		pic->pic_cache->bit_size.y = image.height;
104 		pic->pic_cache->size_x = image.width * scale;
105 		pic->pic_cache->size_y = image.height * scale;
106 		XpmFreeXpmImage(&image);	/* get rid of the image */
107 		/* if monochrome display map bitmap */
108 		if (tool_cells <= 2 || appres.monochrome)
109 			map_to_mono(pic);
110 
111 		return PicSuccess;
112 	}
113 	return FileInvalid;
114 }
115