1 /****************************************************************************
2 Copyright (C) 1987-2015 by Jeffery P. Hansen
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program 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
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 Last edit by hansen on Tue Jan 20 14:47:22 2009
19 ****************************************************************************/
20 #include <stdlib.h>
21 #include "tkgate.h"
22 #include <X11/Xutil.h>
23
24 #define DEBUG_ICON 0
25
26 static SHash *icon_pixmaps = 0; /* Table of pixmaps used for gate icons */
27 static NHash *zoomed_pixmaps = 0; /* Table of zoomed versions of icon_pixmaps */
28
init_iconTables(void)29 void init_iconTables(void)
30 {
31 icon_pixmaps = new_SHash_noob();
32 zoomed_pixmaps = new_NHash_noob();
33 }
34
Pixmap_initZoomSet(Pixmap p,int w,int h)35 void Pixmap_initZoomSet(Pixmap p,int w,int h)
36 {
37 int i;
38 PixmapZoomSet *zset;
39
40 zset = (PixmapZoomSet*)malloc(sizeof(PixmapZoomSet));
41 for (i = 0;i < ZOOM_MAX+1;i++)
42 zset->p[i] = 0;
43 zset->p[1] = p;
44 zset->width = w;
45 zset->height = h;
46 NHash_insert(zoomed_pixmaps,p,zset);
47 }
48
Pixmap_deleteZoomSet(Pixmap p)49 void Pixmap_deleteZoomSet(Pixmap p)
50 {
51 PixmapZoomSet *zset;
52 int i;
53
54 zset = (PixmapZoomSet*)NHash_find(zoomed_pixmaps,p);
55 if (!zset) return;
56
57 NHash_remove(zoomed_pixmaps,p);
58
59 for (i = 0;i < ZOOM_MAX+1;i++)
60 if (zset->p[i]) {
61 printf("XFreePixmap(%x)\n",(unsigned)zset->p[i]);
62 XFreePixmap(TkGate.D,zset->p[i]);
63 }
64 free(zset);
65 }
66
Pixmap_register(char * name,unsigned char data[],unsigned w,unsigned h)67 Pixmap Pixmap_register(char *name,unsigned char data[],unsigned w,unsigned h)
68 {
69 Pixmap *P;
70
71 if (!TkGate.tcl) return None;
72
73 if (SHash_find(icon_pixmaps,name))
74 return None;
75
76 P = (Pixmap*) malloc(sizeof(Pixmap));
77 *P = XCreatePixmapFromBitmapData(TkGate.D,TkGate.root,(char*)data,w,h,1,0,1);
78 SHash_insert(icon_pixmaps,name,P);
79 Pixmap_initZoomSet(*P,w,h);
80
81 return *P;
82 }
83
Pixmap_registerFromFileWithParms(char * name,char * file,int * pw,int * ph,int * px,int * py)84 Pixmap Pixmap_registerFromFileWithParms(char *name,char *file,int *pw,int *ph,int *px,int *py)
85 {
86 static const char *base_dir = 0;
87 Pixmap *P;
88 unsigned w,h;
89 int x,y;
90 char buf[STRMAX];
91
92 if (!TkGate.tcl) return None;
93
94
95 if (!base_dir) {
96 base_dir = Tcl_GetVar(TkGate.tcl,"bd",TCL_GLOBAL_ONLY);
97 if (!base_dir) base_dir = "images";
98 }
99
100 sprintf(buf,"%s/%s",base_dir,file);
101
102 if (SHash_find(icon_pixmaps,name))
103 return None;
104
105 P = (Pixmap*) malloc(sizeof(Pixmap));
106
107 if (XReadBitmapFile(TkGate.D,TkGate.root,buf,&w,&h,P,&x,&y) != BitmapSuccess) {
108 fprintf(stderr,"Failed to find required bitmap '%s'\n",buf);
109 exit(1);
110 return None;
111 }
112
113 SHash_insert(icon_pixmaps,name,P);
114 Pixmap_initZoomSet(*P,w,h);
115
116 if (pw) *pw = w;
117 if (ph) *ph = h;
118 if (px) *px = x;
119 if (py) *py = y;
120
121 return *P;
122 }
123
Pixmap_registerFromFile(char * name,char * file)124 Pixmap Pixmap_registerFromFile(char *name,char *file)
125 {
126 return Pixmap_registerFromFileWithParms(name,file,0,0,0,0);
127 }
128
Pixmap_find(char * name)129 Pixmap Pixmap_find(char *name)
130 {
131 Pixmap *P = (Pixmap*) SHash_find(icon_pixmaps,name);
132
133 if (!P) return None;
134
135 return *P;
136 }
137
138 /*
139 * Create a copy of pixmap p magnified by scale factor zp
140 */
Pixmap_createZoomPixmap(Pixmap p,int w,int h,int zp)141 Pixmap Pixmap_createZoomPixmap(Pixmap p,int w,int h,int zp)
142 {
143 XImage *SI = XGetImage(TkGate.D,p,0,0,w,h,0x1,XYPixmap);
144 Pixmap DP = XCreatePixmap(TkGate.D,TkGate.root,zp*w,zp*h,1);
145 XImage *DI = XGetImage(TkGate.D,DP,0,0,zp*w,zp*h,0x1,XYPixmap);
146 int x,y;
147
148 for (x = 0;x < w;x++) {
149 for (y = 0;y < h;y++) {
150 int v = XGetPixel(SI,x,y);
151 int a,b;
152
153 for (a = 0;a < zp;a++)
154 for (b = 0;b < zp;b++)
155 XPutPixel(DI,x*zp+a,y*zp+b,v);
156 }
157 }
158
159 XPutImage(TkGate.D,DP,TkGate.bitGC,DI,0,0,0,0,zp*w,zp*h);
160
161 XDestroyImage(DI);
162 XDestroyImage(SI);
163
164 return DP;
165 }
166
167 /*
168 * Find and/or create zoomed pixmap
169 */
Pixmap_zoom(Pixmap p,int z)170 Pixmap Pixmap_zoom(Pixmap p,int z)
171 {
172 PixmapZoomSet *zset;
173 if (z == 1) return p;
174
175 zset = (PixmapZoomSet*)NHash_find(zoomed_pixmaps,p);
176 if (!zset) return None;
177 if (!zset->p[z]) {
178 zset->p[z] = Pixmap_createZoomPixmap(p,zset->width,zset->height,z);
179 }
180
181 return zset->p[z];
182 }
183
new_Icon(Pixmap P,int x,int y,int w,int h,int ox,int oy)184 Icon *new_Icon(Pixmap P,int x,int y,int w,int h,int ox,int oy)
185 {
186 Icon *I = (Icon*) malloc(sizeof(Icon));
187
188 I->pm = P;
189 I->x = x;
190 I->y = y;
191 I->width = w;
192 I->height = h;
193 I->ox = ox;
194 I->oy = oy;
195
196 #if DEBUG_ICON
197 printf("create icon [%p p=(%d,%d) %dx%d o=(%d,%d) ]\n",
198 I->pm,I->x,I->y,I->width,I->height,I->ox,I->oy);
199 #endif
200 return I;
201 }
202
new_IconID(Pixmap P,iconDimensions * id,int yoffset)203 Icon *new_IconID(Pixmap P,iconDimensions *id,int yoffset)
204 {
205 return new_Icon(P,id->x,id->y+yoffset,id->w,id->h,id->ox,id->oy);
206 }
207
Icon_draw(Display * D,Window W,GC gc,int x,int y,Icon * I)208 void Icon_draw(Display *D,Window W,GC gc,int x,int y,Icon *I)
209 {
210 #if DEBUG_ICON
211 printf("draw icon [%p p=(%d,%d) %dx%d o=(%d,%d) ] @(%d, %d) \n",
212 I->pm,I->x,I->y,I->width,I->height,I->ox,I->oy,x,y);
213 #endif
214 ZCopyPlane(D,I->pm,W,gc,I->x,I->y,I->width,I->height,x-I->ox,y-I->oy,0x1);
215 }
216
217