1 /* Copyright (C) 2000-2012 by George Williams */
2 /*
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are met:
5 
6  * Redistributions of source code must retain the above copyright notice, this
7  * list of conditions and the following disclaimer.
8 
9  * Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12 
13  * The name of the author may not be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15 
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <fontforge-config.h>
29 
30 #include "gdraw.h"
31 #include "gdrawP.h"
32 #include "gkeysym.h"
33 #include "ustring.h"
34 
35 #if __Mac
36 #  include <sys/select.h>
37 #endif
38 
39 /* Functions for font metrics:
40     rectangle of text (left side bearing of first char, right of last char)
41 */
42 
43 GDisplay *screen_display = NULL;
44 void (*_GDraw_BuildCharHook)(GDisplay *) = NULL;
45 void (*_GDraw_InsCharHook)(GDisplay *,unichar_t) = NULL;
46 
GDrawPointsToPixels(GWindow gw,int points)47 int GDrawPointsToPixels(GWindow gw,int points) {
48     if ( gw==NULL ) {
49 	if ( screen_display==NULL )
50 return( PointToPixel(points,100));
51 	gw = screen_display->groot;
52     }
53 return( PointToPixel(points,gw->display->res));
54 }
55 
GDrawPixelsToPoints(GWindow gw,int pixels)56 int GDrawPixelsToPoints(GWindow gw,int pixels) {
57     if ( gw==NULL ) {
58 	if ( screen_display==NULL )
59 return( PixelToPoint(pixels,100));
60 	gw = screen_display->groot;
61     }
62 return( PixelToPoint(pixels,gw->display->res));
63 }
64 
GDrawSetDefaultIcon(GWindow icon)65 void GDrawSetDefaultIcon(GWindow icon) {
66     (icon->display->funcs->setDefaultIcon)(icon);
67 }
68 
GDrawCreateTopWindow(GDisplay * gdisp,GRect * pos,int (* eh)(GWindow,GEvent *),void * user_data,GWindowAttrs * wattrs)69 GWindow GDrawCreateTopWindow(GDisplay *gdisp, GRect *pos,
70 	int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
71     if ( gdisp==NULL ) gdisp = screen_display;
72 return( (gdisp->funcs->createTopWindow)(gdisp,pos,eh,user_data,wattrs) );
73 }
74 
GDrawCreateSubWindow(GWindow w,GRect * pos,int (* eh)(GWindow,GEvent *),void * user_data,GWindowAttrs * wattrs)75 GWindow GDrawCreateSubWindow(GWindow w, GRect *pos,
76 	int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
77 return( (w->display->funcs->createSubWindow)(w,pos,eh,user_data,wattrs) );
78 }
79 
GDrawCreatePixmap(GDisplay * gdisp,GWindow similar,uint16 width,uint16 height)80 GWindow GDrawCreatePixmap(GDisplay *gdisp, GWindow similar, uint16 width, uint16 height) {
81     if ( gdisp==NULL ) gdisp = screen_display;
82 return( (gdisp->funcs->createPixmap)(gdisp,similar,width,height));
83 }
84 
GDrawCreateBitmap(GDisplay * gdisp,uint16 width,uint16 height,uint8 * data)85 GWindow GDrawCreateBitmap(GDisplay *gdisp, uint16 width, uint16 height, uint8 *data) {
86     if ( gdisp==NULL ) gdisp = screen_display;
87 return( (gdisp->funcs->createBitmap)(gdisp,width,height,data));
88 }
89 
GDrawCreateCursor(GWindow src,GWindow mask,Color fg,Color bg,int16 x,int16 y)90 GCursor GDrawCreateCursor(GWindow src,GWindow mask,Color fg,Color bg,
91 	int16 x, int16 y ) {
92 return( (src->display->funcs->createCursor)(src,mask,fg,bg,x,y));
93 }
94 
GDrawDestroyWindow(GWindow w)95 void GDrawDestroyWindow(GWindow w) {
96     (w->display->funcs->destroyWindow)(w);
97 }
98 
GDrawSetZoom(GWindow w,GRect * zoom,enum gzoom_flags flags)99 void GDrawSetZoom(GWindow w,GRect *zoom, enum gzoom_flags flags) {
100     (w->display->funcs->setZoom)(w,zoom,flags);
101 }
102 
GDrawDestroyCursor(GDisplay * gdisp,GCursor ct)103 void GDrawDestroyCursor(GDisplay *gdisp, GCursor ct) {
104     if ( gdisp==NULL ) gdisp = screen_display;
105     (gdisp->funcs->destroyCursor)(gdisp,ct);
106 }
107 
GDrawNativeWindowExists(GDisplay * gdisp,void * native)108 int GDrawNativeWindowExists(GDisplay *gdisp, void *native) {
109     if ( gdisp==NULL ) gdisp = screen_display;
110 return( (gdisp->funcs->nativeWindowExists)(gdisp,native) );
111 }
112 
GDrawSetWindowBackground(GWindow w,Color col)113 void GDrawSetWindowBackground(GWindow w,Color col) {
114     (w->display->funcs->setWindowBackground)(w,col);
115 }
116 
GDrawSetDither(GDisplay * gdisp,int dither)117 int GDrawSetDither(GDisplay *gdisp, int dither) {
118     if ( gdisp==NULL ) gdisp = screen_display;
119 return( (gdisp->funcs->setDither)(gdisp,dither) );
120 }
121 
GDrawSetVisible(GWindow w,int visible)122 void GDrawSetVisible(GWindow w, int visible) {
123     (w->display->funcs->setVisible)(w,visible);
124 }
125 
GDrawIsVisible(GWindow w)126 int GDrawIsVisible(GWindow w) {
127     if ( w==NULL )
128 return( false );
129     while ( w!=NULL && ( w->is_visible || w->is_pixmap ))
130 	w = w->parent;
131 return( w==NULL );
132 }
133 
GDrawMove(GWindow w,int32 x,int32 y)134 void GDrawMove(GWindow w, int32 x, int32 y) {
135     (w->display->funcs->move)(w,x,y);
136 }
137 
GDrawTrueMove(GWindow w,int32 x,int32 y)138 void GDrawTrueMove(GWindow w, int32 x, int32 y) {
139     (w->display->funcs->trueMove)(w,x,y);
140 }
141 
GDrawResize(GWindow w,int32 width,int32 height)142 void GDrawResize(GWindow w, int32 width, int32 height) {
143     (w->display->funcs->resize)(w,width,height);
144 }
145 
GDrawMoveResize(GWindow w,int32 x,int32 y,int32 width,int32 height)146 void GDrawMoveResize(GWindow w, int32 x, int32 y, int32 width, int32 height) {
147     (w->display->funcs->moveResize)(w,x,y,width,height);
148 }
149 
GDrawGetRoot(GDisplay * gdisp)150 GWindow GDrawGetRoot(GDisplay *gdisp) {
151     if ( gdisp==NULL ) gdisp = screen_display;
152 return(gdisp->groot);
153 }
154 
GDrawGetDefaultBackground(GDisplay * gdisp)155 Color GDrawGetDefaultBackground(GDisplay *gdisp) {
156     if ( gdisp==NULL ) gdisp = screen_display;
157 return(gdisp->def_background);
158 }
159 
GDrawGetDefaultForeground(GDisplay * gdisp)160 Color GDrawGetDefaultForeground(GDisplay *gdisp) {
161     if ( gdisp==NULL ) gdisp = screen_display;
162 return(gdisp->def_foreground);
163 }
164 
GDrawGetSize(GWindow w,GRect * ret)165 GRect *GDrawGetSize(GWindow w, GRect *ret) {
166     *ret = w->pos;
167 return(ret);
168 }
169 
GDrawGetEH(GWindow w)170 GDrawEH GDrawGetEH(GWindow w) {
171 return( w->eh );
172 }
173 
GDrawSetEH(GWindow w,GDrawEH eh)174 void GDrawSetEH(GWindow w,GDrawEH eh) {
175     w->eh = eh;
176 }
177 
GDrawGetPointerPosition(GWindow w,GEvent * ret)178 void GDrawGetPointerPosition(GWindow w, GEvent *ret) {
179     (w->display->funcs->getPointerPos)(w,ret);
180 }
181 
GDrawGetPointerWindow(GWindow w)182 GWindow GDrawGetPointerWindow(GWindow w) {
183 return( (w->display->funcs->getPointerWindow)(w));
184 }
185 
GDrawRaise(GWindow w)186 void GDrawRaise(GWindow w) {
187     (w->display->funcs->raise)(w);
188 }
189 
GDrawRaiseAbove(GWindow w,GWindow below)190 void GDrawRaiseAbove(GWindow w,GWindow below) {
191     (w->display->funcs->raiseAbove)(w,below);
192 }
193 
GDrawIsAbove(GWindow w,GWindow other)194 int GDrawIsAbove(GWindow w,GWindow other) {
195 return( (w->display->funcs->isAbove)(w,other) );
196 }
197 
GDrawLower(GWindow w)198 void GDrawLower(GWindow w) {
199     (w->display->funcs->lower)(w);
200 }
201 
GDrawSetWindowTitles(GWindow w,const unichar_t * title,const unichar_t * icontit)202 void GDrawSetWindowTitles(GWindow w, const unichar_t *title, const unichar_t *icontit) {
203     (w->display->funcs->setWindowTitles)(w,title,icontit);
204 }
205 
GDrawGetWindowTitle(GWindow w)206 unichar_t *GDrawGetWindowTitle(GWindow w) {
207 return( (w->display->funcs->getWindowTitle)(w) );
208 }
209 
GDrawSetWindowTitles8(GWindow w,const char * title,const char * icontit)210 void GDrawSetWindowTitles8(GWindow w, const char *title, const char *icontit) {
211     (w->display->funcs->setWindowTitles8)(w,title,icontit);
212 }
213 
GDrawGetWindowTitle8(GWindow w)214 char *GDrawGetWindowTitle8(GWindow w) {
215 return( (w->display->funcs->getWindowTitle8)(w) );
216 }
217 
GDrawSetTransientFor(GWindow transient,GWindow owner)218 void GDrawSetTransientFor(GWindow transient, GWindow owner) {
219     (transient->display->funcs->setTransientFor)(transient,owner);
220 }
221 
GDrawSetCursor(GWindow w,GCursor ct)222 void GDrawSetCursor(GWindow w, GCursor ct) {
223     (w->display->funcs->setCursor)(w,ct);
224 }
225 
GDrawGetCursor(GWindow w)226 GCursor GDrawGetCursor(GWindow w) {
227 return( (w->display->funcs->getCursor)(w) );
228 }
229 
GDrawGetRedirectWindow(GDisplay * gd)230 GWindow GDrawGetRedirectWindow(GDisplay *gd) {
231     if ( gd==NULL ) gd = screen_display;
232 return( (gd->funcs->getRedirectWindow)(gd) );
233 }
234 
GDrawTranslateCoordinates(GWindow from,GWindow to,GPoint * pt)235 void GDrawTranslateCoordinates(GWindow from,GWindow to, GPoint *pt) {
236     GDisplay *gd;
237     if ( from!=NULL )
238 	gd = from->display;
239     else if ( to!=NULL )
240 	gd = to->display;
241     else
242 return;
243     (gd->funcs->translateCoordinates)(from,to,pt);
244 }
245 
GDrawEventInWindow(GWindow inme,GEvent * event)246 int32 GDrawEventInWindow(GWindow inme,GEvent *event) {
247     GPoint pt;
248     if ( event->type<et_char || event->type>et_crossing )
249 return( false );
250     pt.x = event->u.mouse.x; pt.y = event->u.mouse.y;
251     (inme->display->funcs->translateCoordinates)(event->w,inme,&pt);
252     if ( pt.x<0 || pt.y<0 || pt.x >= inme->pos.width || pt.y >= inme->pos.height )
253 return( false );
254 
255 return( true );
256 }
257 
GDrawGetParentWindow(GWindow gw)258 GWindow GDrawGetParentWindow(GWindow gw) {
259 return( gw->parent );
260 }
261 
GDrawWindowIsAncestor(GWindow ancester,GWindow descendent)262 int GDrawWindowIsAncestor(GWindow ancester, GWindow descendent) {
263     while ( descendent!=NULL && descendent!=ancester )
264 	descendent = descendent->parent;
265 return( descendent==ancester );
266 }
267 
GDrawSetUserData(GWindow gw,void * ud)268 void GDrawSetUserData(GWindow gw, void *ud) {
269     gw->user_data = ud;
270 }
271 
GDrawGetUserData(GWindow gw)272 void *GDrawGetUserData(GWindow gw) {
273     if( !gw )
274 	return 0;
275 return( gw->user_data );
276 }
277 
GDrawSetWindowTypeName(GWindow gw,char * name)278 void GDrawSetWindowTypeName(GWindow gw, char* name)
279 {
280     gw->window_type_name = name;
281 }
282 
GDrawGetWindowTypeName(GWindow gw)283 char* GDrawGetWindowTypeName(GWindow gw)
284 {
285     if(!gw)
286 	return 0;
287 
288     return(gw->window_type_name);
289 }
290 
291 
GDrawGetDisplayOfWindow(GWindow gw)292 GDisplay *GDrawGetDisplayOfWindow(GWindow gw) {
293     if ( gw==NULL )
294 return( screen_display );
295 
296 return( gw->display );
297 }
298 
GDrawBeep(GDisplay * gdisp)299 void GDrawBeep(GDisplay *gdisp) {
300     if ( gdisp==NULL ) gdisp = screen_display;
301     (gdisp->funcs->beep)(gdisp);
302 }
303 
GDrawGetClip(GWindow w,GRect * ret)304 void GDrawGetClip(GWindow w, GRect *ret) {
305     *ret = w->ggc->clip;
306 }
307 
GDrawSetClip(GWindow w,GRect * rct)308 void GDrawSetClip(GWindow w, GRect *rct) {
309     if ( rct==NULL ) {
310 	w->ggc->clip.x = w->ggc->clip.y = 0;
311 	w->ggc->clip.width = w->ggc->clip.height = 0x7fff;
312     } else
313 	w->ggc->clip = *rct;
314 }
315 
GDrawPushClip(GWindow w,GRect * rct,GRect * old)316 void GDrawPushClip(GWindow w, GRect *rct, GRect *old) {
317     (w->display->funcs->pushClip)(w,rct,old);
318 }
319 
GDrawPushClipOnly(GWindow w)320 void GDrawPushClipOnly(GWindow w)
321 {
322     if( w->display->funcs->PushClipOnly )
323         (w->display->funcs->PushClipOnly)( w );
324 }
325 
GDrawClipPreserve(GWindow w)326 void GDrawClipPreserve(GWindow w)
327 {
328     if( w->display->funcs->ClipPreserve )
329         (w->display->funcs->ClipPreserve)( w );
330 }
331 
332 
GDrawPopClip(GWindow w,GRect * old)333 void GDrawPopClip(GWindow w, GRect *old) {
334     (w->display->funcs->popClip)(w,old);
335 }
336 
337 
GDrawGetWindowGGC(GWindow w)338 GGC *GDrawGetWindowGGC(GWindow w) {
339 return( w->ggc );
340 }
341 
GDrawSetDifferenceMode(GWindow w)342 void GDrawSetDifferenceMode(GWindow w) {
343     (w->display->funcs->setDifferenceMode)(w);
344 }
345 
GDrawSetDashedLine(GWindow w,int16 dash_len,int16 skip_len,int16 off)346 void GDrawSetDashedLine(GWindow w,int16 dash_len, int16 skip_len, int16 off) {
347     w->ggc->dash_offset = off;
348     w->ggc->dash_len = dash_len;
349     w->ggc->skip_len = skip_len;
350 }
351 
GDrawSetStippled(GWindow w,int16 ts,int32 yoff,int32 xoff)352 void GDrawSetStippled(GWindow w,int16 ts, int32 yoff,int32 xoff) {
353     w->ggc->ts = ts;
354     w->ggc->ts_xoff = xoff; w->ggc->ts_yoff = yoff;
355 }
356 
GDrawSetLineWidth(GWindow w,int16 width)357 void GDrawSetLineWidth(GWindow w,int16 width) {
358     w->ggc->line_width = width;
359 }
360 
GDrawGetLineWidth(GWindow w)361 int16 GDrawGetLineWidth( GWindow w )
362 {
363     return w->ggc->line_width;
364 }
365 
366 
GDrawSetForeground(GWindow w,Color col)367 void GDrawSetForeground(GWindow w,Color col) {
368     w->ggc->fg = col;
369 }
370 
GDrawSetBackground(GWindow w,Color col)371 void GDrawSetBackground(GWindow w,Color col) {
372     w->ggc->bg = col;
373 }
374 
GDrawClear(GWindow w,GRect * rect)375 void GDrawClear(GWindow w, GRect *rect) {
376     (w->display->funcs->clear)(w,rect);
377 }
378 
GDrawDrawLine(GWindow w,int32 x,int32 y,int32 xend,int32 yend,Color col)379 void GDrawDrawLine(GWindow w, int32 x,int32 y, int32 xend,int32 yend, Color col) {
380     if ( col!=COLOR_UNKNOWN )
381 	(w->display->funcs->drawLine)(w,x,y,xend,yend,col);
382 }
383 
GDrawDrawArrow(GWindow w,int32 x,int32 y,int32 xend,int32 yend,int arrows,Color col)384 void GDrawDrawArrow(GWindow w, int32 x,int32 y, int32 xend,int32 yend, int arrows, Color col) {
385     if ( col!=COLOR_UNKNOWN )
386 	(w->display->funcs->drawArrow)(w,x,y,xend,yend,arrows,col);
387 }
388 
GDrawDrawRect(GWindow w,GRect * rect,Color col)389 void GDrawDrawRect(GWindow w, GRect *rect, Color col) {
390     if ( col!=COLOR_UNKNOWN )
391 	(w->display->funcs->drawRect)(w,rect,col);
392 }
393 
GDrawFillRect(GWindow w,GRect * rect,Color col)394 void GDrawFillRect(GWindow w, GRect *rect, Color col) {
395     GRect temp;
396     if ( rect==NULL ) {
397 	temp.x = temp.y = 0; temp.width = w->pos.width; temp.height = w->pos.height;
398 	rect = &temp;
399     }
400     if ( col!=COLOR_UNKNOWN )
401 	(w->display->funcs->fillRect)(w,rect,col);
402 }
403 
GDrawFillRoundRect(GWindow w,GRect * rect,int radius,Color col)404 void GDrawFillRoundRect(GWindow w, GRect *rect, int radius, Color col) {
405     GRect temp;
406     if ( rect==NULL ) {
407 	temp.x = temp.y = 0; temp.width = w->pos.width; temp.height = w->pos.height;
408 	rect = &temp;
409     }
410     if ( col!=COLOR_UNKNOWN )
411 	(w->display->funcs->fillRoundRect)(w,rect,radius,col);
412 }
413 
GDrawDrawElipse(GWindow w,GRect * rect,Color col)414 void GDrawDrawElipse(GWindow w, GRect *rect, Color col) {
415     if ( col!=COLOR_UNKNOWN )
416 	(w->display->funcs->drawElipse)(w,rect,col);
417 }
418 
GDrawFillElipse(GWindow w,GRect * rect,Color col)419 void GDrawFillElipse(GWindow w, GRect *rect, Color col) {
420     if ( col!=COLOR_UNKNOWN )
421 	(w->display->funcs->fillElipse)(w,rect,col);
422 }
423 
424 /* angles expressed as in X, in 64's of a degree with 0 angle at 3 o'clock */
425 /*  and positive measured counter-clockwise (or the same way as in polar coords)*/
426 /* tangle is NOT the end angle, it's the angle offset from the first to the end*/
GDrawDrawArc(GWindow w,GRect * rect,int32 sangle,int32 tangle,Color col)427 void GDrawDrawArc(GWindow w, GRect *rect, int32 sangle, int32 tangle, Color col) {
428     if ( col!=COLOR_UNKNOWN )
429 	(w->display->funcs->drawArc)(w,rect,sangle,tangle,col);
430 }
431 
GDrawDrawPoly(GWindow w,GPoint * pts,int16 cnt,Color col)432 void GDrawDrawPoly(GWindow w, GPoint *pts, int16 cnt, Color col) {
433     if ( col!=COLOR_UNKNOWN )
434 	(w->display->funcs->drawPoly)(w,pts,cnt,col);
435 }
436 
GDrawFillPoly(GWindow w,GPoint * pts,int16 cnt,Color col)437 void GDrawFillPoly(GWindow w, GPoint *pts, int16 cnt, Color col) {
438     if ( col!=COLOR_UNKNOWN )
439 	(w->display->funcs->fillPoly)(w,pts,cnt,col);
440 }
441 
GDrawScroll(GWindow w,GRect * rect,int32 hor,int32 vert)442 void GDrawScroll(GWindow w, GRect *rect, int32 hor, int32 vert) {
443     (w->display->funcs->scroll)(w,rect,hor,vert);
444 }
445 
446 /* draws the subset of the image specified by src starting at loc (x,y) */
GDrawDrawImage(GWindow w,GImage * img,GRect * src,int32 x,int32 y)447 void GDrawDrawImage(GWindow w, GImage *img, GRect *src, int32 x, int32 y) {
448     int width = GImageGetWidth(img);
449     int height = GImageGetHeight(img);
450     GRect r = src ? *src : (GRect){0, 0, width, height};
451 
452     if (x < w->ggc->clip.x) {
453         r.x += w->ggc->clip.x - x;
454         r.width -= w->ggc->clip.x - x;
455         x = w->ggc->clip.x;
456     }
457     if (y < w->ggc->clip.y) {
458         r.y += w->ggc->clip.y - y;
459         r.height -= w->ggc->clip.y - y;
460         y = w->ggc->clip.y;
461     }
462     if (r.x < 0) {
463         r.width += r.x;
464         r.x = 0;
465     }
466     if (r.y < 0) {
467         r.height += r.y;
468         r.y = 0;
469     }
470     if (r.width > width)
471         r.width = width;
472     if (r.height > height)
473         r.height = height;
474     if (x + r.width > w->ggc->clip.x + w->ggc->clip.width)
475         r.width = w->ggc->clip.x + w->ggc->clip.width - x;
476     if (y + r.height > w->ggc->clip.y + w->ggc->clip.height)
477         r.height = w->ggc->clip.y + w->ggc->clip.height - y;
478     if (r.width <= 0 || r.height <= 0)
479         return;
480 
481     (w->display->funcs->drawImage)(w,img,&r,x,y);
482 }
483 
484 /* Draw the entire image so that it is approximately the same size on other */
485 /*  displays as on the screen */
GDrawDrawScaledImage(GWindow w,GImage * img,int32 x,int32 y)486 void GDrawDrawScaledImage(GWindow w, GImage *img, int32 x, int32 y) {
487     GRect r;
488 
489     r.x = r.y = 0;
490     r.width = GImageGetScaledWidth(w,img);
491     r.height = GImageGetScaledHeight(w,img);
492     (w->display->funcs->drawImage)(w,img,&r,x,y);
493 }
494 
495 /* Similar to DrawImage, but can in some cases make improvements -- if the */
496 /*  is an indexed image, then treat as the alpha channel rather than a color */
497 /*  in its own right */
GDrawDrawGlyph(GWindow w,GImage * img,GRect * src,int32 x,int32 y)498 void GDrawDrawGlyph(GWindow w, GImage *img, GRect *src, int32 x, int32 y) {
499     GRect r;
500     if ( src==NULL ) {
501 	struct _GImage *base = img->list_len==0?img->u.image:img->u.images[0];
502 	r.x = r.y = 0;
503 	r.width = base->width; r.height = base->height;
504 	src = &r;
505     }
506     (w->display->funcs->drawGlyph)(w,img,src,x,y);
507 }
508 
509 /* same as drawImage except with pixmaps */
GDrawDrawPixmap(GWindow w,GWindow pixmap,GRect * src,int32 x,int32 y)510 void GDrawDrawPixmap(GWindow w, GWindow pixmap, GRect *src, int32 x, int32 y) {
511     (w->display->funcs->drawPixmap)(w,pixmap,src,x,y);
512 }
513 
514 /* We assume the full image is drawn starting at (x,y) and scaled to (width,height) */
515 /*  this routine updates the rectangle on the screen			 */
516 /*		(x+src->x,y+src->y,x+src->width,y+src->height)		 */
517 /* Ie. if you get an expose event in the middle of the image subtract off the */
518 /*  image base (x,y) and pass in the exposed rectangle */
GDrawDrawImageMagnified(GWindow w,GImage * img,GRect * dest,int32 x,int32 y,int32 width,int32 height)519 void GDrawDrawImageMagnified(GWindow w, GImage *img, GRect *dest, int32 x, int32 y,
520 	int32 width, int32 height) {
521     GRect temp;
522     struct _GImage *base = img->list_len==0?img->u.image:img->u.images[0];
523 
524     /* Not magnified after all */
525     if ( base->width==width && base->height==height ) {
526         GDrawDrawImage(w, img, dest, x, y);
527         return;
528     }
529     if ( dest==NULL ) {
530 	temp.x = temp.y = 0;
531 	temp.width = width; temp.height = height;
532 	dest = &temp;
533     } else if ( dest->x<0 || dest->y<0 ||
534 	    dest->x+dest->width > width || dest->y+dest->height > height ) {
535 	temp = *dest;
536 	if ( temp.x<0 ) { temp.width += temp.x; temp.x = 0; }
537 	if ( temp.y<0 ) { temp.height += temp.y; temp.y = 0; }
538 	if ( temp.x+temp.width>width ) temp.width = width-temp.x;
539 	if ( temp.y+temp.height>height ) temp.height = height-temp.y;
540 	dest = &temp;
541     }
542     (w->display->funcs->drawImageMag)(w,img,dest,x,y, width, height);
543 }
544 
GDrawWindowFontMetrics(GWindow w,FontInstance * fi,int * as,int * ds,int * ld)545 void GDrawWindowFontMetrics(GWindow w,FontInstance *fi,int *as, int *ds, int *ld) {
546     (w->display->funcs->getFontMetrics)(w,fi,as,ds,ld);
547 }
548 
549 
GDrawHasCairo(GWindow w)550 enum gcairo_flags GDrawHasCairo(GWindow w) {
551 return( (w->display->funcs->hasCairo)(w));
552 }
553 
GDrawPathStartNew(GWindow w)554 void GDrawPathStartNew(GWindow w) {
555     (w->display->funcs->startNewPath)(w);
556 }
557 
GDrawPathStartSubNew(GWindow w)558 void GDrawPathStartSubNew(GWindow w) {
559     (w->display->funcs->startNewSubPath)(w);
560 }
561 
GDrawFillRuleSetWinding(GWindow w)562 int GDrawFillRuleSetWinding(GWindow w) {
563     return (w->display->funcs->fillRuleSetWinding)(w);
564 }
565 
GDrawPathClose(GWindow w)566 void GDrawPathClose(GWindow w) {
567     (w->display->funcs->closePath)(w);
568 }
569 
GDrawPathMoveTo(GWindow w,double x,double y)570 void GDrawPathMoveTo(GWindow w,double x, double y) {
571     (w->display->funcs->moveto)(w,x,y);
572 }
573 
GDrawPathLineTo(GWindow w,double x,double y)574 void GDrawPathLineTo(GWindow w,double x, double y) {
575     (w->display->funcs->lineto)(w,x,y);
576 }
577 
GDrawPathCurveTo(GWindow w,double cx1,double cy1,double cx2,double cy2,double x,double y)578 void GDrawPathCurveTo(GWindow w,
579 		    double cx1, double cy1,
580 		    double cx2, double cy2,
581 		    double x, double y) {
582     (w->display->funcs->curveto)(w,cx1,cy1,cx2,cy2,x,y);
583 }
584 
GDrawPathStroke(GWindow w,Color col)585 void GDrawPathStroke(GWindow w,Color col) {
586     (w->display->funcs->stroke)(w,col);
587 }
588 
GDrawPathFill(GWindow w,Color col)589 void GDrawPathFill(GWindow w,Color col) {
590     (w->display->funcs->fill)(w,col);
591 }
592 
GDrawPathFillAndStroke(GWindow w,Color fillcol,Color strokecol)593 void GDrawPathFillAndStroke(GWindow w,Color fillcol, Color strokecol) {
594     (w->display->funcs->fillAndStroke)(w,fillcol,strokecol);
595 }
596 
GDrawLayoutInit(GWindow w,char * text,int cnt,GFont * fi)597 void GDrawLayoutInit(GWindow w, char *text, int cnt, GFont *fi) {
598     (w->display->funcs->layoutInit)(w,text,cnt,fi);
599 }
600 
GDrawLayoutDraw(GWindow w,int32 x,int32 y,Color fg)601 void GDrawLayoutDraw(GWindow w, int32 x, int32 y, Color fg) {
602     (w->display->funcs->layoutDraw)(w,x,y,fg);
603 }
604 
GDrawLayoutIndexToPos(GWindow w,int index,GRect * pos)605 void GDrawLayoutIndexToPos(GWindow w, int index, GRect *pos) {
606     (w->display->funcs->layoutIndexToPos)(w,index,pos);
607 }
608 
GDrawLayoutXYToIndex(GWindow w,int x,int y)609 int GDrawLayoutXYToIndex(GWindow w, int x, int y) {
610 return( (w->display->funcs->layoutXYToIndex)(w,x,y) );
611 }
612 
GDrawLayoutExtents(GWindow w,GRect * size)613 void GDrawLayoutExtents(GWindow w, GRect *size) {
614     (w->display->funcs->layoutExtents)(w,size);
615 }
616 
GDrawLayoutSetWidth(GWindow w,int width)617 void GDrawLayoutSetWidth(GWindow w, int width) {
618     (w->display->funcs->layoutSetWidth)(w,width);
619 }
620 
GDrawLayoutLineCount(GWindow w)621 int  GDrawLayoutLineCount(GWindow w) {
622 return( (w->display->funcs->layoutLineCount)(w) );
623 }
624 
GDrawLayoutLineStart(GWindow w,int line)625 int  GDrawLayoutLineStart(GWindow w,int line) {
626 return( (w->display->funcs->layoutLineStart)(w,line) );
627 }
628 
629 
GDrawCreateInputContext(GWindow w,enum gic_style def_style)630 GIC *GDrawCreateInputContext(GWindow w,enum gic_style def_style) {
631 return(w->display->funcs->createInputContext)(w,def_style);
632 }
633 
GDrawSetGIC(GWindow w,GIC * gic,int x,int y)634 void GDrawSetGIC(GWindow w, GIC *gic, int x, int y) {
635     (w->display->funcs->setGIC)(w,gic,x,y);
636 }
637 
GDrawKeyState(GWindow w,int keysym)638 int GDrawKeyState(GWindow w, int keysym) {
639     return (w->display->funcs->keyState)(w, keysym);
640 }
641 
GDrawGrabSelection(GWindow w,enum selnames sel)642 void GDrawGrabSelection(GWindow w,enum selnames sel) {
643     (w->display->funcs->grabSelection)(w,sel);
644 }
645 
GDrawAddSelectionType(GWindow w,enum selnames sel,char * type,void * data,int32 cnt,int32 unitsize,void * (* gendata)(void *,int32 * len),void (* freedata)(void *))646 void GDrawAddSelectionType(GWindow w,enum selnames sel,char *type,
647 	void *data,int32 cnt,int32 unitsize,void *(*gendata)(void *,int32 *len),
648 	void (*freedata)(void *)) {
649     (w->display->funcs->addSelectionType)(w,sel,type,data,cnt,unitsize,gendata,freedata);
650 }
651 
GDrawRequestSelection(GWindow w,enum selnames sn,char * typename,int32 * len)652 void *GDrawRequestSelection(GWindow w,enum selnames sn, char *typename, int32 *len) {
653 return( (w->display->funcs->requestSelection)(w,sn,typename,len));
654 }
655 
GDrawSelectionHasType(GWindow w,enum selnames sn,char * typename)656 int GDrawSelectionHasType(GWindow w,enum selnames sn, char *typename) {
657 return( (w->display->funcs->selectionHasType)(w,sn,typename));
658 }
659 
GDrawBindSelection(GDisplay * disp,enum selnames sel,char * atomname)660 void GDrawBindSelection(GDisplay *disp,enum selnames sel, char *atomname) {
661     if ( disp==NULL )
662 	disp = screen_display;
663     if (disp != NULL)
664         (disp->funcs->bindSelection)(disp,sel,atomname);
665 }
666 
GDrawSelectionOwned(GDisplay * disp,enum selnames sel)667 int GDrawSelectionOwned(GDisplay *disp,enum selnames sel) {
668     if ( disp==NULL )
669 	disp = screen_display;
670     if (disp != NULL)
671         return( (disp->funcs->selectionHasOwner)(disp,sel));
672     else
673         return -1;
674 }
675 
GDrawEnableExposeRequests(GWindow w,int enabled)676 int GDrawEnableExposeRequests(GWindow w,int enabled) {
677     int old = w->disable_expose_requests;
678     w->disable_expose_requests = enabled;
679 return( old );
680 }
681 
GDrawRequestExpose(GWindow w,GRect * rect,int doclear)682 void GDrawRequestExpose(GWindow w, GRect *rect, int doclear) {
683     if ( !GDrawIsVisible(w) || w->disable_expose_requests )
684 return;
685     (w->display->funcs->requestExpose)(w,rect,doclear);
686 }
687 
GDrawForceUpdate(GWindow w)688 void GDrawForceUpdate(GWindow w) {
689     (w->display->funcs->forceUpdate)(w);
690 }
691 
GDrawSync(GDisplay * gdisp)692 void GDrawSync(GDisplay *gdisp) {
693     if ( gdisp==NULL ) gdisp=screen_display;
694     if (gdisp != NULL)
695     (gdisp->funcs->sync)(gdisp);
696 }
697 
GDrawPointerUngrab(GDisplay * gdisp)698 void GDrawPointerUngrab(GDisplay *gdisp) {
699     if ( gdisp==NULL ) gdisp=screen_display;
700     if (gdisp != NULL)
701     (gdisp->funcs->pointerUngrab)(gdisp);
702 }
703 
GDrawPointerGrab(GWindow w)704 void GDrawPointerGrab(GWindow w) {
705     (w->display->funcs->pointerGrab)(w);
706 }
707 
GDrawProcessOneEvent(GDisplay * gdisp)708 void GDrawProcessOneEvent(GDisplay *gdisp) {
709     if ( gdisp==NULL ) gdisp=screen_display;
710     if (gdisp != NULL)
711     (gdisp->funcs->processOneEvent)(gdisp);
712 }
713 
GDrawSkipMouseMoveEvents(GWindow w,GEvent * last)714 void GDrawSkipMouseMoveEvents(GWindow w,GEvent *last) {
715     (w->display->funcs->skipMouseMoveEvents)(w,last);
716 }
717 
GDrawProcessPendingEvents(GDisplay * gdisp)718 void GDrawProcessPendingEvents(GDisplay *gdisp) {
719     if ( gdisp==NULL ) gdisp=screen_display;
720     if (gdisp != NULL)
721     (gdisp->funcs->processPendingEvents)(gdisp);
722 }
723 
GDrawProcessWindowEvents(GWindow w)724 void GDrawProcessWindowEvents(GWindow w) {
725     (w->display->funcs->processWindowEvents)(w);
726 }
727 
GDrawEventLoop(GDisplay * gdisp)728 void GDrawEventLoop(GDisplay *gdisp) {
729     if ( gdisp==NULL ) gdisp=screen_display;
730     if (gdisp != NULL)
731     (gdisp->funcs->eventLoop)(gdisp);
732 }
733 
GDrawPostEvent(GEvent * e)734 void GDrawPostEvent(GEvent *e) {
735     GDisplay *gdisp = e->w->display;
736     if ( gdisp==NULL ) gdisp=screen_display;
737     if (gdisp != NULL)
738     (gdisp->funcs->postEvent)(e);
739 }
740 
GDrawPostDragEvent(GWindow w,GEvent * mouse,enum event_type et)741 void GDrawPostDragEvent(GWindow w,GEvent *mouse,enum event_type et) {
742     GDisplay *gdisp = w->display;
743     (gdisp->funcs->postDragEvent)(w,mouse,et);
744 }
745 
GDrawRequestTimer(GWindow w,int32 time_from_now,int32 frequency,void * userdata)746 GTimer *GDrawRequestTimer(GWindow w,int32 time_from_now,int32 frequency,
747 	void *userdata) {
748 return( (w->display->funcs->requestTimer)(w,time_from_now,frequency,userdata));
749 }
750 
GDrawCancelTimer(GTimer * timer)751 void GDrawCancelTimer(GTimer *timer) {
752     GDisplay *gdisp;
753     if ( timer==NULL )
754 return;
755     gdisp=timer->owner->display;
756     (gdisp->funcs->cancelTimer)(timer);
757 }
758 
GDrawRequestDeviceEvents(GWindow w,int devcnt,struct gdeveventmask * de)759 int GDrawRequestDeviceEvents(GWindow w,int devcnt,struct gdeveventmask *de) {
760 return( (w->display->funcs->requestDeviceEvents)(w,devcnt,de) );
761 }
762 
GDrawSetBuildCharHooks(void (* hook)(GDisplay *),void (* inshook)(GDisplay *,unichar_t))763 void GDrawSetBuildCharHooks(void (*hook)(GDisplay *),void (*inshook)(GDisplay *,unichar_t)) {
764     _GDraw_BuildCharHook = hook;
765     _GDraw_InsCharHook = inshook;
766 }
767 
768 /* We are in compose characters mode. The gdisp->mykey_state argument tells us*/
769 /*  how many accent keys have been pressed. When we finally get a non-accent */
770 /*  we try to look through our rules for composing letters given this set of */
771 /*  accents and this base character. If we find something, great, install it */
772 /*  and return. If there's nothing then see if we get anywhere by removing */
773 /*  one of the accents (if so use it, but continue with the remain accent in */
774 /*  the state). Finally we use the base character followed by all the accents */
775 /*  left unaccounted for in the mask */
_GDraw_ComposeChars(GDisplay * gdisp,GEvent * gevent)776 void _GDraw_ComposeChars(GDisplay *gdisp,GEvent *gevent) {
777     unichar_t ch = gevent->u.chr.keysym;
778     struct gchr_transform *strt = NULL, *trans, *end=NULL;
779     extern struct gchr_lookup _gdraw_chrlookup[];
780     extern struct gchr_accents _gdraw_accents[];
781     extern uint32 _gdraw_chrs_ctlmask, _gdraw_chrs_metamask, _gdraw_chrs_any;
782     int i,mask;
783     unichar_t hold[_GD_EVT_CHRLEN], *pt, *ept, *hpt;
784     uint32 mykey_state = gdisp->mykey_state;
785 
786     if ( gevent->u.chr.chars[0]=='\0' )		/* ignore things like the shift key */
787 return;
788     if ( gevent->u.chr.keysym==GK_Escape ) {
789 	gevent->u.chr.chars[0] = '\0';
790 	gevent->u.chr.keysym = '\0';
791 	gdisp->mykeybuild = false;
792 return;
793     }
794     if ( gevent->u.chr.state&ksm_control )
795 	mykey_state |= _gdraw_chrs_ctlmask;
796     if ( gevent->u.chr.state&ksm_meta )
797 	mykey_state |= _gdraw_chrs_metamask;
798     if ( ch>' ' && ch<0x7f ) {
799 	for ( trans = strt = _gdraw_chrlookup[ch-' '].transtab, end=trans+_gdraw_chrlookup[ch-' '].cnt;
800 		trans<end; ++trans ) {
801 	    if ( trans->oldstate==mykey_state ) {
802 		gdisp->mykey_state = trans->newstate;
803 		if ( trans->resch=='\0' )
804 		    u_strcpy(gevent->u.chr.chars,gevent->u.chr.chars+1);
805 		else {
806 		    gevent->u.chr.chars[0] = trans->resch;
807 		    gdisp->mykeybuild = false;
808 		}
809 return;
810 	    } else if ( trans->oldstate==_gdraw_chrs_any ) {
811 		gdisp->mykey_state |= trans->newstate;
812 		u_strcpy(gevent->u.chr.chars,gevent->u.chr.chars+1);
813 return;
814 	    }
815 	}
816     }
817 
818     GDrawBeep(gdisp);
819     if ( mykey_state==0 || mykey_state==0x8000000 )
820 return;
821     u_strcpy(hold,gevent->u.chr.chars+1);
822     if ( strt!=NULL ) for ( mask=0x1; mask<0x8000000; mask<<=1 ) {
823 	if ( (mykey_state&~mask)== 0 )
824     break;			/* otherwise dotabove a gives us ae */
825 	for ( trans=strt; trans<end; ++trans ) {
826 	    if ( trans->oldstate==(mykey_state&~mask) && trans->resch!='\0' ) {
827 		mykey_state = mask;
828 		gevent->u.chr.chars[0] = trans->resch;
829     goto break_2_loops;
830 	    }
831 	}
832     }
833     break_2_loops:;
834     pt = gevent->u.chr.chars+1; ept = gevent->u.chr.chars+_GD_EVT_CHRLEN-1;
835     for ( i=0; _gdraw_accents[i].accent!=0 && pt<ept; ++i ) {
836 	if ( (_gdraw_accents[i].mask&mykey_state)==_gdraw_accents[i].mask ) {
837 	    *pt++ = _gdraw_accents[i].accent;
838 	    mykey_state &= ~_gdraw_accents[i].mask;
839 	}
840     }
841     for ( hpt = hold; pt<ept && *hpt!='\0'; )
842 	*pt++ = *hpt++;
843     *pt = '\0';
844     gdisp->mykeybuild = false;
845 }
846 
GDrawDestroyDisplays()847 void GDrawDestroyDisplays() {
848   if (screen_display != NULL) {
849 #ifndef FONTFORGE_CAN_USE_GDK
850     _GXDraw_DestroyDisplay(screen_display);
851 #else
852     _GGDKDraw_DestroyDisplay(screen_display);
853 #endif
854     screen_display = NULL;
855   }
856 }
857 
GDrawCreateDisplays(char * displayname,char * programname)858 void GDrawCreateDisplays(char *displayname,char *programname) {
859 #ifndef FONTFORGE_CAN_USE_GDK
860     screen_display = _GXDraw_CreateDisplay(displayname,programname);
861 #else
862     screen_display = _GGDKDraw_CreateDisplay(displayname, programname);
863 #endif
864     if ( screen_display==NULL ) {
865 	fprintf( stderr, "Could not open screen.\n" );
866 #if __Mac
867 	fprintf( stderr, "You must start X11 before you can start %s\n", programname);
868 	fprintf( stderr, " X11 is optional software found on your install DVD.\n" );
869 #elif __CygWin
870 	fprintf( stderr, "You must start X11 before you can start %s\n", programname);
871 	fprintf( stderr, " X11 may be obtained from the cygwin site in a separate package.\n" );
872 #endif
873 exit(1);
874     }
875 }
876