1 /************************************************************************/
2 /*									*/
3 /*  Drawing surface implementation implementation.			*/
4 /*									*/
5 /************************************************************************/
6 
7 #   include "appFrameConfig.h"
8 
9 #   include "guiWidgetDrawingSurface.h"
10 #   include <drawDrawingSurface.h>
11 #   include "drawDrawingSurfaceImpl.h"
12 #   include "drawScreenFontImpl.h"
13 #   include "drawTextImplX11.h"
14 #   include "drawScreenFontAdmin.h"
15 #   include "drawUtilMotif.h"
16 #   include "drawImpl.h"
17 #   include "drawImplXft.h"
18 #   include <appDebugon.h>
19 
20 #   ifdef USE_MOTIF
21 
22 /************************************************************************/
23 
drawMakeDrawingSurfaceForParent(DrawingSurface parent,int wide,int high)24 DrawingSurface drawMakeDrawingSurfaceForParent(
25 				DrawingSurface			parent,
26 				int				wide,
27 				int				high )
28     {
29     int			depth;
30     DrawingSurface	ds= malloc(sizeof(struct DrawingSurface));
31 
32     if  ( ! ds )
33 	{ PDEB(ds); return ds;	}
34     drawInitDrawingSurface( ds );
35 
36     depth= DefaultDepth( parent->dsDisplay, parent->dsScreen );
37 
38     ds->dsDisplay= parent->dsDisplay;
39     ds->dsScreen= parent->dsScreen;
40 
41     ds->dsColors= parent->dsColors;
42     ds->dsDrawable= XCreatePixmap( parent->dsDisplay, parent->dsDrawable,
43 							wide, high, depth );
44     ds->dsAvoidFontconfig= parent->dsAvoidFontconfig;
45     ds->dsIsPixmap= 1;
46 
47     if  ( ! ds->dsDrawable )
48 	{
49 	XDEB(ds->dsDrawable);
50 	drawFreeDrawingSurface( ds );
51 	return (DrawingSurface)0;
52 	}
53 
54     ds->dsGc= XCreateGC( ds->dsDisplay, ds->dsDrawable, 0, NULL );
55     if  ( ! ds->dsGc )
56 	{
57 	XDEB(ds->dsGc);
58 	drawFreeDrawingSurface( ds );
59 	return (DrawingSurface)0;
60 	}
61 
62 #   ifdef USE_XFT
63     if  ( ! ds->dsAvoidFontconfig )
64 	{
65 	ds->dsXftDrawable= appMotifXftDrawCreate(
66 				ds->dsDisplay, ds->dsScreen,
67 				ds->dsDrawable, &(ds->dsXftColorList) );
68 	if  ( ! ds->dsXftDrawable )
69 	    { XDEB(ds->dsXftDrawable);	}
70 	}
71 #   endif
72 
73     return ds;
74     }
75 
drawMakeDrawingSurfaceForImageAndParent(DrawingSurface parent,const RasterImage * abi,const DocumentRectangle * drSrc,int pixelsWide,int pixelsHigh)76 DrawingSurface drawMakeDrawingSurfaceForImageAndParent(
77 				DrawingSurface			parent,
78 				const RasterImage *		abi,
79 				const DocumentRectangle *	drSrc,
80 				int				pixelsWide,
81 				int				pixelsHigh )
82     {
83     DrawingSurface	ds;
84     APP_IMAGE *		xim= (APP_IMAGE *)0;
85 
86     ds= drawMakeDrawingSurfaceForParent( parent, pixelsWide, pixelsHigh );
87     if  ( ! ds )
88 	{ XDEB(ds); return ds;	}
89 
90     if  ( drawUtilMotifMakeImage( ds->dsDisplay, ds->dsScreen,
91 					    &xim, pixelsWide, pixelsHigh,
92 					    ds->dsColors, abi, drSrc ) )
93 	{ drawFreeDrawingSurface( ds ); return (DrawingSurface)0;	}
94 
95     XPutImage( ds->dsDisplay, ds->dsDrawable, ds->dsGc, xim, 0, 0, 0, 0,
96 						pixelsWide, pixelsHigh );
97 
98     XDestroyImage( xim );
99 
100     return ds;
101     }
102 
103 /************************************************************************/
104 
drawRasterImage(DrawingSurface ds,const DocumentRectangle * drDest,const RasterImage * abi,const DocumentRectangle * drSrc)105 int drawRasterImage(		DrawingSurface			ds,
106 				const DocumentRectangle *	drDest,
107 				const RasterImage *		abi,
108 				const DocumentRectangle *	drSrc )
109     {
110     APP_IMAGE *		xim= (APP_IMAGE *)0;
111     int			pixelsWide= drDest->drX1- drDest->drX0+ 1;
112     int			pixelsHigh= drDest->drY1- drDest->drY0+ 1;
113 
114     if  ( drawUtilMotifMakeImage( ds->dsDisplay, ds->dsScreen,
115 					    &xim, pixelsWide, pixelsHigh,
116 					    ds->dsColors, abi, drSrc ) )
117 	{ LLDEB(pixelsWide,pixelsHigh); return -1;	}
118 
119     XPutImage( ds->dsDisplay, ds->dsDrawable, ds->dsGc, xim, 0, 0,
120 						drDest->drX0, drDest->drY0,
121 						pixelsWide, pixelsHigh );
122 
123     XDestroyImage( xim );
124 
125     return 0;
126     }
127 
128 /************************************************************************/
129 /*									*/
130 /*  Cause subsequent drawing to be done in a certain color.		*/
131 /*									*/
132 /************************************************************************/
133 
drawSetForegroundColor(DrawingSurface ds,const RGB8Color * rgb8)134 int drawSetForegroundColor(	DrawingSurface		ds,
135 				const RGB8Color *	rgb8 )
136     {
137     APP_COLOR_RGB		xc;
138 
139     if  ( appColorRgb( &xc, ds->dsColors,
140 				    rgb8->rgb8Red,
141 				    rgb8->rgb8Green,
142 				    rgb8->rgb8Blue ) )
143 	{ LDEB(1); return -1;	}
144 
145     XSetForeground( ds->dsDisplay, ds->dsGc, xc.pixel );
146 
147 #   ifdef USE_XFT
148     appSolidXftColor( &(ds->dsXftColorList.axclCurrentColor), &xc );
149 #   endif
150 
151     return 0;
152     }
153 
154 /************************************************************************/
155 /*									*/
156 /*  Destroy a drawing surface. Only free resources allocated by the	*/
157 /*  DrawingSurface itself.						*/
158 /*									*/
159 /*  1)  Older versions of GTK/XFT crash here if the cleaning action is	*/
160 /*	called from a destroy callback. MdD Jun 2007.			*/
161 /*									*/
162 /************************************************************************/
163 
drawFreeDrawingSurface(DrawingSurface ds)164 void drawFreeDrawingSurface(	DrawingSurface		ds )
165     {
166 #   ifdef USE_XFT
167     appCleanAppXftColorList( &(ds->dsXftColorList) );
168 
169     /*  1  */
170     if  ( ds->dsXftDrawable )
171 	{ XftDrawDestroy( ds->dsXftDrawable );	}
172 #   endif
173 
174     if  ( ds->dsGc )
175 	{ XFreeGC( ds->dsDisplay, ds->dsGc );	}
176 
177     if  ( ds->dsPoints )
178 	{ free( ds->dsPoints );	}
179 
180     if  ( ds->dsIsPixmap )
181 	{ XFreePixmap( ds->dsDisplay, ds->dsDrawable );	}
182 
183     free( ds );
184     }
185 
186 
187 /************************************************************************/
188 /*									*/
189 /*  Fill a rectangle.							*/
190 /*									*/
191 /************************************************************************/
192 
drawFillRectangle(DrawingSurface ds,const DocumentRectangle * dr)193 void drawFillRectangle(	DrawingSurface			ds,
194 			const DocumentRectangle *	dr )
195     {
196 #   ifdef USE_XFT
197     if  ( ! drawFillRectangleXft( ds->dsXftDrawable,
198 						&(ds->dsXftColorList), dr ) )
199 	{ return;	}
200 #   endif
201 
202     XFillRectangle( ds->dsDisplay, ds->dsDrawable, ds->dsGc,
203 			dr->drX0, dr->drY0,
204 			dr->drX1- dr->drX0+ 1, dr->drY1- dr->drY0+ 1 );
205     }
206 
drawRectangle(DrawingSurface ds,const DocumentRectangle * dr)207 void drawRectangle(	DrawingSurface			ds,
208 			const DocumentRectangle *	dr )
209     {
210     XDrawRectangle( ds->dsDisplay, ds->dsDrawable, ds->dsGc,
211 			dr->drX0, dr->drY0,
212 			dr->drX1- dr->drX0+ 1, dr->drY1- dr->drY0+ 1 );
213     }
214 
215 /************************************************************************/
216 /*									*/
217 /*  Draw a line.							*/
218 /*									*/
219 /************************************************************************/
220 
drawLine(DrawingSurface ds,int x0,int y0,int x1,int y1)221 int drawLine(		DrawingSurface			ds,
222 			int				x0,
223 			int				y0,
224 			int				x1,
225 			int				y1 )
226     {
227     XDrawLine( ds->dsDisplay, ds->dsDrawable, ds->dsGc, x0, y0, x1, y1 );
228     return 0;
229     }
230 
231 /************************************************************************/
232 /*									*/
233 /*  Convert points to native type.					*/
234 /*									*/
235 /************************************************************************/
236 
drawSetPoints(DrawingSurface ds,const Point2DI * points,int pointCount)237 static int drawSetPoints(	DrawingSurface		ds,
238 				const Point2DI *	points,
239 				int			pointCount )
240     {
241     int			i;
242 
243     if  ( ds->dsPointCount < pointCount )
244 	{
245 	APP_POINT *	fresh= (APP_POINT *)realloc( ds->dsPoints,
246 					    pointCount* sizeof(APP_POINT) );
247 	if  ( ! fresh )
248 	    { LXDEB(pointCount,fresh); return -1;	}
249 
250 	ds->dsPoints= fresh;
251 	ds->dsPointCount= pointCount;
252 	}
253 
254     for ( i= 0; i < pointCount; i++ )
255 	{
256 	ds->dsPoints[i].x= points[i].x;
257 	ds->dsPoints[i].y= points[i].y;
258 	}
259 
260     return 0;
261     }
262 
263 /************************************************************************/
264 /*									*/
265 /*  Draw a series of lines.						*/
266 /*									*/
267 /************************************************************************/
268 
drawLines(DrawingSurface ds,const Point2DI * points,int pointCount,int close)269 int drawLines(		DrawingSurface			ds,
270 			const Point2DI *		points,
271 			int				pointCount,
272 			int				close )
273     {
274     int		i;
275 
276     if  ( drawSetPoints( ds, points, pointCount ) )
277 	{ LDEB(pointCount); return -1;	}
278 
279     pointCount--;
280 
281     for ( i= 0; i < pointCount; i++ )
282 	{
283 	XDrawLine( ds->dsDisplay, ds->dsDrawable, ds->dsGc,
284 				    ds->dsPoints[i+0].x, ds->dsPoints[i+0].y,
285 				    ds->dsPoints[i+1].x, ds->dsPoints[i+1].y );
286 	}
287 
288     if  ( close )
289 	{
290 	XDrawLine( ds->dsDisplay, ds->dsDrawable, ds->dsGc,
291 				    ds->dsPoints[i].x, ds->dsPoints[i].y,
292 				    ds->dsPoints[0].x, ds->dsPoints[0].y );
293 	}
294 
295     return 0;
296     }
297 
298 /************************************************************************/
299 /*									*/
300 /*  Fill a polygon.							*/
301 /*									*/
302 /************************************************************************/
303 
drawFillPolygon(DrawingSurface ds,const Point2DI * points,int pointCount)304 int drawFillPolygon(	DrawingSurface			ds,
305 			const Point2DI *		points,
306 			int				pointCount )
307     {
308     if  ( drawSetPoints( ds, points, pointCount ) )
309 	{ LDEB(pointCount); return -1;	}
310 
311     XFillPolygon( ds->dsDisplay, ds->dsDrawable, ds->dsGc,
312 						ds->dsPoints, pointCount,
313 						Complex, CoordModeOrigin );
314 
315     return 0;
316     }
317 
318 /************************************************************************/
319 /*									*/
320 /*  Set line attributes.						*/
321 /*									*/
322 /************************************************************************/
323 
324 static const int LineStyleMap[LineStyle_Count]=
325     { LineSolid, LineOnOffDash, LineDoubleDash,	};
326 
327 static const int CapStyleMap[LineCap_Count]=
328     { CapNotLast, CapButt, CapRound, CapProjecting	};
329 
330 static const int JoinStyleMap[LineJoin_Count]=
331     { JoinMiter, JoinRound, JoinBevel	};
332 
drawSetLineAttributes(DrawingSurface ds,int lineWidth,int lineStyle,int capStyle,int joinStyle,const unsigned char * dashList,int dashCount)333 int drawSetLineAttributes(	DrawingSurface		ds,
334 				int			lineWidth,
335 				int			lineStyle,
336 				int			capStyle,
337 				int			joinStyle,
338 				const unsigned char *	dashList,
339 				int			dashCount )
340     {
341     XSetLineAttributes( ds->dsDisplay, ds->dsGc, lineWidth,
342 				LineStyleMap[lineStyle],
343 				CapStyleMap[capStyle],
344 				JoinStyleMap[joinStyle] );
345 
346     if  ( lineStyle != LineStyleSolid )
347 	{
348 	if  ( ! dashList || dashCount == 0 )
349 	    { XLDEB(dashList,dashCount);	}
350 	else{
351 	    XSetDashes( ds->dsDisplay, ds->dsGc,
352 					0, (char *)dashList, dashCount );
353 	    }
354 	}
355 
356     return 0;
357     }
358 
drawArc(DrawingSurface ds,const Arc2DI * arc)359 void drawArc(			DrawingSurface		ds,
360 				const Arc2DI *		arc )
361     {
362     XDrawArc( ds->dsDisplay, ds->dsDrawable, ds->dsGc,
363 				    arc->a2diRect.drX0, arc->a2diRect.drY0,
364 				    arc->a2diRect.drX1- arc->a2diRect.drX0+ 1,
365 				    arc->a2diRect.drY1- arc->a2diRect.drY0+ 1,
366 				    arc->a2diAngleFrom, arc->a2diAngleStep );
367     }
368 
drawFillArc(DrawingSurface ds,const Arc2DI * arc)369 void drawFillArc(		DrawingSurface		ds,
370 				const Arc2DI *		arc )
371     {
372     XFillArc( ds->dsDisplay, ds->dsDrawable, ds->dsGc,
373 				    arc->a2diRect.drX0, arc->a2diRect.drY0,
374 				    arc->a2diRect.drX1- arc->a2diRect.drX0+ 1,
375 				    arc->a2diRect.drY1- arc->a2diRect.drY0+ 1,
376 				    arc->a2diAngleFrom, arc->a2diAngleStep );
377     }
378 
379 /************************************************************************/
380 /*									*/
381 /*  Set a cached system color as the current foreground color.		*/
382 /*									*/
383 /************************************************************************/
384 
drawSetSystemColor(DrawingSurface ds,APP_COLOR_RGB * xc)385 void drawSetSystemColor(	DrawingSurface			ds,
386 				APP_COLOR_RGB *			xc )
387     {
388     XSetForeground( ds->dsDisplay, ds->dsGc, xc->pixel );
389 
390 #   ifdef USE_XFT
391     appSolidXftColor( &(ds->dsXftColorList.axclCurrentColor), xc );
392 #   endif
393     }
394 
395 /************************************************************************/
396 /*									*/
397 /*  Draw a string.							*/
398 /*									*/
399 /************************************************************************/
400 
drawString(DrawingSurface ds,int x0,int y0,int screenFont,const char * s,int len)401 int drawString(		DrawingSurface			ds,
402 			int				x0,
403 			int				y0,
404 			int				screenFont,
405 			const char *			s,
406 			int				len )
407     {
408     const NumberedPropertiesList *	npl= &(ds->dsScreenFontAdmin);
409     DrawScreenFont *			dsf;
410 
411     TextProgress			tp;
412 
413     dsf= drawGetScreenFontByNumber( npl, screenFont );
414     if  ( ! dsf )
415 	{ LXDEB(screenFont,dsf); return -1;	}
416 
417     /* HACK: Font might have been allocated before the widget wasrealized */
418     if  ( ! dsf->dsfDrawable )
419 	{ dsf->dsfDrawable= ds->dsDrawable;	}
420     if  ( ! dsf->dsfGc )
421 	{ dsf->dsfGc= ds->dsGc;	}
422 
423 #   ifdef USE_XFT
424     if  ( ! dsf->dsfXftDrawable )
425 	{ dsf->dsfXftDrawable= ds->dsXftDrawable;	}
426 
427     if  ( dsf->dsfXftDrawable						&&
428 	  dsf->dsfXftFont						&&
429 	  ! drawStringXft( dsf, &(ds->dsXftColorList), x0, y0, s, len )	)
430 	{ return 0;	}
431 #   endif
432 
433     tp.tpX= x0;
434     tp.tpY= y0;
435 
436     drawHandleTextSegmentsX11( &tp, dsf, s, len, drawTextSegment8X11,
437 			    drawTextSegment16X11, &(dsf->dsfEncodedFonts) );
438 
439     return 0;
440     }
441 
drawOpenScreenFont(DrawingSurface ds,const AfmFontInfo * afi,int pixelSize,const IndexSet * unicodesWanted)442 int drawOpenScreenFont(		DrawingSurface			ds,
443 				const AfmFontInfo *		afi,
444 				int				pixelSize,
445 				const IndexSet *		unicodesWanted)
446     {
447     DrawScreenFont *	dsf;
448     int			fresh;
449     int			screenFont;
450 
451     screenFont= drawGetScreenFont( &dsf, &fresh, &(ds->dsScreenFontAdmin),
452 					    unicodesWanted, afi, pixelSize );
453     if  ( screenFont < 0 )
454 	{ LDEB(screenFont); return -1;	}
455 
456     if  ( fresh )
457 	{
458 	if  ( ! dsf->dsfDisplay )
459 	    { dsf->dsfDisplay= ds->dsDisplay;	}
460 	if  ( ! dsf->dsfDrawable )
461 	    { dsf->dsfDrawable= ds->dsDrawable;	}
462 	if  ( ! dsf->dsfGc )
463 	    { dsf->dsfGc= ds->dsGc;	}
464 
465 	if  ( drawFontOpenScreenFont( dsf, ds->dsAvoidFontconfig ) )
466 	    { LDEB(1); return -1;	}
467 	}
468 
469     return screenFont;
470     }
471 
drawNoClipping(DrawingSurface ds)472 void drawNoClipping(		DrawingSurface		ds )
473     {
474 #   ifdef USE_XFT
475     if  ( ds->dsXftDrawable )
476 	{
477 	XftDrawSetClip( ds->dsXftDrawable, 0 );
478 	}
479 #   endif
480 
481     XSetClipMask( ds->dsDisplay, ds->dsGc, None );
482 
483     return;
484     }
485 
drawSetClipRect(DrawingSurface ds,const DocumentRectangle * drClip)486 void drawSetClipRect(	DrawingSurface			ds,
487 			const DocumentRectangle *	drClip )
488     {
489     XRectangle	xRect;
490 
491     xRect.x= drClip->drX0;
492     xRect.y= drClip->drY0;
493     xRect.width= drClip->drX1- drClip->drX0+ 1;
494     xRect.height= drClip->drY1- drClip->drY0+ 1;
495 
496     if  ( xRect.width < 1 || xRect.height < 1 )
497 	{ LLDEB(xRect.width,xRect.height); return;	}
498 
499 #   ifdef USE_XFT
500     if  ( ds->dsXftDrawable )
501 	{
502 	XftDrawSetClipRectangles( ds->dsXftDrawable, 0, 0, &xRect, 1 );
503 	}
504 #   endif
505 
506     XSetClipRectangles( ds->dsDisplay, ds->dsGc, 0, 0, &xRect, 1, Unsorted );
507 
508     return;
509     }
510 
511 /************************************************************************/
512 
drawChildSurface(DrawingSurface ds,const DrawingSurface child,int xDest,int yDest,const DocumentRectangle * drChild)513 void drawChildSurface(		DrawingSurface			ds,
514 				const DrawingSurface		child,
515 				int				xDest,
516 				int				yDest,
517 				const DocumentRectangle *	drChild )
518     {
519     if  ( drChild->drX1 >= drChild->drX0	&&
520 	  drChild->drY1 >= drChild->drY0	)
521 	{
522 	XCopyArea( ds->dsDisplay, child->dsDrawable, ds->dsDrawable, ds->dsGc,
523 				drChild->drX0, drChild->drY0,
524 				drChild->drX1- drChild->drX0+ 1,
525 				drChild->drY1- drChild->drY0+ 1,
526 				xDest, yDest );
527 	}
528 
529     return;
530     }
531 
532 
533 /************************************************************************/
534 
drawMoveArea(DrawingSurface ds,int xDest,int yDest,const DocumentRectangle * drSrc)535 void drawMoveArea(		DrawingSurface			ds,
536 				int				xDest,
537 				int				yDest,
538 				const DocumentRectangle *	drSrc )
539     {
540     XCopyArea( ds->dsDisplay, ds->dsDrawable, ds->dsDrawable, ds->dsGc,
541 				drSrc->drX0, drSrc->drY0,
542 				drSrc->drX1- drSrc->drX0+ 1,
543 				drSrc->drY1- drSrc->drY0+ 1,
544 				xDest, yDest );
545     }
546 
547 #   endif
548