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