1 /* libwmf ("ipa/x/device.h"): library for wmf conversion
2    Copyright (C) 2000 - various; see CREDITS, ChangeLog, and sources
3 
4    The libwmf Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8 
9    The libwmf Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public
15    License along with the libwmf Library; see the file COPYING.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18 
19 
20 /* This is called by wmf_play() the *first* time the meta file is played
21  */
wmf_x_device_open(wmfAPI * API)22 static void wmf_x_device_open (wmfAPI* API)
23 {	wmf_x_t* ddata = WMF_X_GetData (API);
24 
25 	XWindowAttributes root_attributes;
26 
27 	XTextProperty wText;
28 	XSizeHints sizehints;
29 
30 	XSetWindowAttributes attributes;
31 
32 	unsigned int border;
33 
34 	unsigned long valuemask;
35 
36 	static char* default_name = "libwmf (x)";
37 
38 	WMF_DEBUG (API,"wmf_[x_]device_open");
39 
40 	if ((!(ddata->x_width > 0)) || (!(ddata->x_height > 0)))
41 	{	WMF_ERROR (API,"window/pixmap has unset or bad size.");
42 		API->err = wmf_E_Glitch;
43 		return;
44 	}
45 
46 	if (ddata->flags & WMF_X_DISPLAY_OPEN)
47 	{	ddata->flags &= ~WMF_X_DISPLAY_CLOSE;
48 		ddata->flags &= ~WMF_X_WINDOW_OPEN;
49 		ddata->flags &= ~WMF_X_WINDOW_CLOSE;
50 		ddata->flags &= ~WMF_X_PIXMAP_OPEN;
51 		ddata->flags &= ~WMF_X_PIXMAP_CLOSE;
52 
53 		ddata->flags &= ~WMF_X_CMAP_DESTROY;
54 
55 		ddata->display = XOpenDisplay (ddata->display_name);
56 
57 		if (ddata->display == 0)
58 		{	WMF_ERROR (API,"unable to open display!");
59 			API->err = wmf_E_DeviceError;
60 			return;
61 		}
62 
63 		ddata->flags |= WMF_X_DISPLAY_CLOSE;
64 		ddata->flags |= WMF_X_WINDOW_OPEN;
65 		ddata->flags |= WMF_X_PIXMAP_OPEN;
66 	}
67 	else /* display already open */
68 	{	if (ddata->display == 0)
69 		{	WMF_ERROR (API,"display not open!");
70 			API->err = wmf_E_DeviceError;
71 			return;
72 		}
73 	}
74 
75 	ddata->root = RootWindow (ddata->display,DefaultScreen (ddata->display));
76 
77 	XGetWindowAttributes (ddata->display,ddata->root,&root_attributes);
78 
79 	ddata->visual = root_attributes.visual;
80 	ddata->depth  = root_attributes.depth;
81 
82 #if defined(__cplusplus) || defined(c_plusplus)
83 	ddata->class = ddata->visual->c_class;  /* C++ class of screen (monochrome, etc.) */
84 #else
85 	ddata->class = ddata->visual->class;    /*     class of screen (monochrome, etc.) */
86 #endif
87 
88 	setup_color (API);
89 
90 	if (ERR (API))
91 	{	WMF_DEBUG (API,"bailing...");
92 		return;
93 	}
94 
95 	ddata->gc = XCreateGC (ddata->display,ddata->root,0,0);
96 
97 	if (ddata->gc == 0)
98 	{	WMF_ERROR (API,"unable to create gc!");
99 		API->err = wmf_E_DeviceError;
100 		return;
101 	}
102 
103 	XSetForeground (ddata->display,ddata->gc,ddata->white);
104 
105 	if (ddata->flags & WMF_X_WINDOW_OPEN)
106 	{	ddata->flags &= ~WMF_X_WINDOW_CLOSE;
107 
108 		border = 0; /* Default border size. */
109 
110 		valuemask = 0;
111 
112 		valuemask |= CWBackPixel;
113 		attributes.background_pixel = ddata->white;
114 
115 		valuemask |= CWColormap;
116 		attributes.colormap = ddata->colormap;
117 
118 		ddata->window = XCreateWindow (ddata->display,ddata->root,0,0,
119 		                               ddata->x_width,ddata->x_height,border,ddata->depth,
120 		                               InputOutput,ddata->visual,valuemask,&attributes);
121 
122 		if (ddata->window == None)
123 		{	WMF_ERROR (API,"unable to create window!");
124 			API->err = wmf_E_DeviceError;
125 			return;
126 		}
127 
128 		ddata->flags |= WMF_X_WINDOW_CLOSE;
129 
130 		XFillRectangle (ddata->display,ddata->window,ddata->gc,
131 		                0,0,ddata->x_width,ddata->x_height);
132 
133 		/* Window manager stuff
134 		 */
135 		if (ddata->window_name == 0) ddata->window_name = default_name;
136 		if (ddata->icon_name   == 0) ddata->icon_name   = default_name;
137 
138 		XStringListToTextProperty (&(ddata->window_name),1,&wText);
139 		XSetWMName (ddata->display,ddata->window,&wText);
140 
141 		XStringListToTextProperty (&(ddata->icon_name)  ,1,&wText);
142 		XSetWMIconName (ddata->display,ddata->window,&wText);
143 
144 		sizehints.flags = PSize;
145 
146 		sizehints.width  = (int) ddata->x_width;
147 		sizehints.height = (int) ddata->x_height;
148 
149 		XSetWMNormalHints (ddata->display,ddata->window,&sizehints);
150 
151 		XMapWindow (ddata->display,ddata->window);
152 	}
153 
154 	if (ddata->flags & WMF_X_PIXMAP_OPEN)
155 	{	ddata->flags &= ~WMF_X_PIXMAP_CLOSE;
156 
157 		ddata->pixmap = XCreatePixmap (ddata->display,ddata->root,
158 		                               ddata->x_width,ddata->x_height,ddata->depth);
159 
160 		if (ddata->pixmap == None)
161 		{	WMF_ERROR (API,"unable to create pixmap!");
162 			API->err = wmf_E_DeviceError;
163 			return;
164 		}
165 
166 		ddata->flags |= WMF_X_PIXMAP_CLOSE;
167 
168 		XFillRectangle (ddata->display,ddata->pixmap,ddata->gc,
169 		                0,0,ddata->x_width,ddata->x_height);
170 
171 		if (ddata->window != None)
172 		{	XSetWindowBackgroundPixmap (ddata->display,ddata->window,ddata->pixmap);
173 			XClearWindow (ddata->display,ddata->window);
174 		}
175 	}
176 
177 	XFlush (ddata->display);
178 }
179 
180 /* This is called by wmf_api_destroy()
181  */
wmf_x_device_close(wmfAPI * API)182 static void wmf_x_device_close (wmfAPI* API)
183 {	wmf_x_t* ddata = WMF_X_GetData (API);
184 
185 	WMF_DEBUG (API,"wmf_[x_]device_close");
186 
187 	if (ddata->hatch != None) XFreePixmap (ddata->display,ddata->hatch);
188 	if (ddata->brush != None) XFreePixmap (ddata->display,ddata->brush);
189 
190 	if (ddata->gc) XFreeGC (ddata->display,ddata->gc);
191 
192 	if (ddata->flags & WMF_X_CMAP_DESTROY)  XFreeColormap  (ddata->display,ddata->colormap);
193 	if (ddata->flags & WMF_X_WINDOW_CLOSE)  XDestroyWindow (ddata->display,ddata->window);
194 	if (ddata->flags & WMF_X_PIXMAP_CLOSE)  XFreePixmap    (ddata->display,ddata->pixmap);
195 	if (ddata->flags & WMF_X_DISPLAY_CLOSE) XCloseDisplay  (ddata->display);
196 }
197 
198 /* This is called from the beginning of each play for initial page setup
199  */
wmf_x_device_begin(wmfAPI * API)200 static void wmf_x_device_begin (wmfAPI* API)
201 {	wmf_x_t* ddata = WMF_X_GetData (API);
202 
203 	WMF_DEBUG (API,"wmf_[x_]device_begin");
204 
205 	setdefaultstyle (API);
206 
207 	XSetClipMask (ddata->display,ddata->gc,None);
208 
209 	XSetForeground (ddata->display,ddata->gc,ddata->white);
210 
211 	if (ddata->window != None)
212 		XFillRectangle (ddata->display,ddata->window,ddata->gc,
213 		                0,0,ddata->x_width,ddata->x_height);
214 	if (ddata->pixmap != None)
215 		XFillRectangle (ddata->display,ddata->pixmap,ddata->gc,
216 		                0,0,ddata->x_width,ddata->x_height);
217 
218 	XFlush (ddata->display);
219 }
220 
221 /* This is called from the end of each play for page termination
222  */
wmf_x_device_end(wmfAPI * API)223 static void wmf_x_device_end (wmfAPI* API)
224 {	wmf_x_t* ddata = WMF_X_GetData (API);
225 
226 	WMF_DEBUG (API,"wmf_[x_]device_end");
227 
228 	XFlush (ddata->display);
229 }
230 
231 /* translation & scaling functions
232  */
x_translate(wmfAPI * API,wmfD_Coord d_pt)233 static XPoint x_translate (wmfAPI* API,wmfD_Coord d_pt)
234 {	return (x_translate_ft64 (API,d_pt,0));
235 }
236 
x_translate_ft64(wmfAPI * API,wmfD_Coord d_pt,FT_Vector * pen)237 static XPoint x_translate_ft64 (wmfAPI* API,wmfD_Coord d_pt,FT_Vector* pen)
238 {	wmf_x_t* ddata = WMF_X_GetData (API);
239 
240 	XPoint x_pt;
241 
242 	double x;
243 	double y;
244 
245 	x = ((double) d_pt.x - (double) ddata->bbox.TL.x);
246 	x /= ((double) ddata->bbox.BR.x - (double) ddata->bbox.TL.x);
247 	x *= (double) ddata->x_width;
248 
249 	y = ((double) d_pt.y - (double) ddata->bbox.TL.y);
250 	y /= ((double) ddata->bbox.BR.y - (double) ddata->bbox.TL.y);
251 	y *= (double) ddata->x_height;
252 
253 	x_pt.x = (short) floor (x);
254 	x_pt.y = (short) floor (y);
255 
256 	if (pen)
257 	{	pen->x = floor ((x - floor (x)) * 64);
258 		pen->y = floor ((y - floor (y)) * 64);
259 	}
260 
261 	return (x_pt);
262 }
263 
x_width(wmfAPI * API,float wmf_width)264 static float x_width (wmfAPI* API,float wmf_width)
265 {	wmf_x_t* ddata = WMF_X_GetData (API);
266 
267 	double width;
268 
269 	width = (double) wmf_width * (double) ddata->x_width;
270 	width /= ((double) ddata->bbox.BR.x - (double) ddata->bbox.TL.x);
271 
272 	return ((float) width);
273 }
274 
x_height(wmfAPI * API,float wmf_height)275 static float x_height (wmfAPI* API,float wmf_height)
276 {	wmf_x_t* ddata = WMF_X_GetData (API);
277 
278 	double height;
279 
280 	height = (double) wmf_height * (double) ddata->x_height;
281 	height /= ((double) ddata->bbox.BR.y - (double) ddata->bbox.TL.y);
282 
283 	return ((float) height);
284 }
285