1
2 /*
3 A* -------------------------------------------------------------------
4 B* This file contains source code for the PyMOL computer program
5 C* copyright 1998-2003 by Warren Lyford Delano of DeLano Scientific.
6 D* -------------------------------------------------------------------
7 E* It is unlawful to modify or remove this copyright notice.
8 F* -------------------------------------------------------------------
9 G* Please see the accompanying LICENSE file for further information.
10 H* --------------------------------------------------\-----------------
11 I* Additional authors of this source file include:
12 -*
13 -*
14 -*
15 Z* -------------------------------------------------------------------
16 */
17 #include"os_python.h"
18
19 #include"os_gl.h"
20 #include"OOMac.h"
21 #include"MemoryDebug.h"
22 #include"Feedback.h"
23 #include"P.h"
24 #include"PConv.h"
25 #include"VFont.h"
26
27 #define VFONT_MASK 0xFF
28
29 typedef struct {
30 int face;
31 float size;
32 int style;
33 ov_diff offset[VFONT_MASK + 1];
34 float advance[VFONT_MASK + 1];
35 float *pen;
36 } VFontRec;
37
38 struct _CVFont {
39 VFontRec **Font;
40 int NFont;
41 };
42
43 //#ifndef _PYMOL_NOPY
VFontRecNew(PyMOLGlobals * G)44 static VFontRec *VFontRecNew(PyMOLGlobals * G)
45 {
46 int a;
47 OOAlloc(G, VFontRec);
48 for(a = 0; a <= VFONT_MASK; a++) {
49 I->advance[a] = 0.0F;
50 I->offset[a] = -1;
51 }
52 I->pen = VLAlloc(float, 1000);
53 return (I);
54 }
55 //#endif
56
VFontWriteToCGO(PyMOLGlobals * G,int font_id,CGO * cgo,const char * text,float * pos,float * scale,float * matrix,float * color)57 int VFontWriteToCGO(PyMOLGlobals * G, int font_id, CGO * cgo,
58 const char *text, float *pos, float *scale, float *matrix, float *color)
59 {
60 CVFont *I = G->VFont;
61 VFontRec *fr = NULL;
62 int ok = true;
63 float base[3], pen[3];
64 float *pc;
65 unsigned char c;
66 int drawing, stroke;
67 float *cgo_verts, *tmp_ptr;
68 ov_diff offset;
69 if((font_id > 0) && (font_id <= I->NFont)) {
70 fr = I->Font[font_id];
71 if(fr)
72 while(1) {
73 c = *(text++);
74 if(!c)
75 break;
76 offset = fr->offset[c];
77 if(offset >= 0) {
78 pc = fr->pen + offset;
79 copy3f(pos, base);
80 drawing = true;
81 stroke = false;
82 while(drawing) {
83 switch ((int) *(pc++)) {
84 case -1: /* sentinel */
85 drawing = false;
86 break;
87 case 0: /* moveto */
88 pen[0] = (*(pc++)) * scale[0];
89 pen[1] = (*(pc++)) * scale[1];
90 pen[2] = 0.0;
91 if(matrix)
92 transform33f3f(matrix, pen, pen);
93 add3f(base, pen, pen);
94 if(stroke) {
95 CGOEnd(cgo);
96 }
97 CGOBegin(cgo, GL_LINE_STRIP);
98 if (color)
99 CGOColorv(cgo, color);
100 CGOVertexv(cgo, pen);
101 stroke = true;
102 break;
103 case 1: /* drawto */
104 pen[0] = (*(pc++)) * scale[0];
105 pen[1] = (*(pc++)) * scale[1];
106 pen[2] = 0.0;
107 if(matrix)
108 transform33f3f(matrix, pen, pen);
109 add3f(base, pen, pen);
110 if(stroke) {
111 (void)tmp_ptr;
112 (void)cgo_verts;
113 CGOVertexv(cgo, pen);
114 }
115 break;
116 default:
117 drawing = false;
118 break;
119 }
120 }
121 pen[0] = fr->advance[c] * scale[0];
122 pen[1] = 0.0;
123 pen[2] = 0.0;
124 if(matrix)
125 transform33f3f(matrix, pen, pen);
126 add3f(pen, pos, pos);
127 if(stroke){
128 CGOEnd(cgo);
129 }
130 }
131 }
132 } else {
133 PRINTFB(G, FB_VFont, FB_Errors)
134 "VFontWriteToCGO-Error: invalid font identifier (%d)\n", font_id ENDFB(G);
135 ok = false;
136 }
137 return (ok);
138 }
139
VFontIndent(PyMOLGlobals * G,int font_id,const char * text,float * pos,float * scale,float * matrix,float dir)140 int VFontIndent(PyMOLGlobals * G, int font_id, const char *text, float *pos, float *scale,
141 float *matrix, float dir)
142 {
143 CVFont *I = G->VFont;
144 VFontRec *fr = NULL;
145 int ok = true;
146 float pen[3];
147 unsigned char c;
148 ov_diff offset;
149
150 if((font_id > 0) && (font_id <= I->NFont)) {
151 fr = I->Font[font_id];
152 if(fr)
153 while(1) {
154 c = *(text++);
155 if(!c)
156 break;
157 offset = fr->offset[c];
158 if(offset >= 0) {
159 pen[0] = fr->advance[c] * scale[0] * dir;
160 pen[1] = 0.0;
161 pen[2] = 0.0;
162 if(matrix)
163 transform33f3f(matrix, pen, pen);
164 add3f(pen, pos, pos);
165 }
166 }
167 } else {
168 PRINTFB(G, FB_VFont, FB_Errors)
169 "VFontIndent-Error: invalid font identifier (%d)\n", font_id ENDFB(G);
170 ok = false;
171 }
172 return (ok);
173 }
174
175 #ifndef _PYMOL_NOPY
VFontRecLoad(PyMOLGlobals * G,VFontRec * I,PyObject * dict)176 static int VFontRecLoad(PyMOLGlobals * G, VFontRec * I, PyObject * dict)
177 { /* assumes blocked Python interpreter */
178
179 ov_diff used = 0;
180 int ok = true;
181 PyObject *key, *char_list;
182 PyObject *stroke_list = NULL;
183 Py_ssize_t pos = 0;
184 unsigned char code[2];
185 float adv;
186 ov_diff n_float;
187 while(PyDict_Next(dict, &pos, &key, &char_list)) {
188 if(!PConvPyStrToStr(key, (char *) code, 2)) {
189 PRINTFB(G, FB_VFont, FB_Errors)
190 "VFont-Error: Bad character code." ENDFB(G);
191 ok = false;
192 } else {
193 if(ok)
194 ok = (char_list != NULL);
195 if(ok)
196 ok = PyList_Check(char_list);
197 if(ok)
198 ok = (PyList_Size(char_list) >= 2);
199 if(ok)
200 ok = PConvPyObjectToFloat(PyList_GetItem(char_list, 0), &adv);
201 if(ok) {
202 stroke_list = PyList_GetItem(char_list, 1);
203 if(ok)
204 ok = (stroke_list != NULL);
205 if(ok)
206 ok = PyList_Check(stroke_list);
207 if(ok) {
208 n_float = PyList_Size(stroke_list);
209 VLACheck(I->pen, float, n_float + used + 1);
210 ok = PConvPyListToFloatArrayInPlace(stroke_list, I->pen + used, n_float);
211 I->offset[code[0]] = used;
212 I->advance[code[0]] = adv;
213 I->pen[used + n_float] = -1.0F; /* sentinel */
214 PRINTFD(G, FB_VFont)
215 " VFontRecLoad-Debug: Added '%c' adv: %0.3f n_float: %d\n", code[0], adv,
216 (int)n_float ENDFD;
217 if(ok)
218 used += n_float + 1;
219
220 }
221 }
222 }
223 }
224 return (ok);
225 }
226 #else
227 #include "vfontdata.h"
228
VFontRecLoad(PyMOLGlobals * G,VFontRec * I)229 static int VFontRecLoad(PyMOLGlobals * G, VFontRec * I)
230 {
231 ov_diff used = 0;
232 int ok = true;
233 int chidx, n_float, i, off;
234 float adv;
235
236 for (chidx=0;chidx<VFONT_NUMBER_OF_CHARS; chidx++){
237 adv = advs[chidx];
238 n_float = n_floats[chidx];
239 VLACheck(I->pen, float, n_float + used + 1);
240 off = stroke_list_place[chidx];
241 for (i=0;i<n_float;i++){
242 *(I->pen + used + i) = stroke_lists[off+i];
243 }
244 I->offset[ch[chidx]] = used;
245 I->advance[ch[chidx]] = adv;
246 I->pen[used + n_float] = -1.0F; /* sentinel */
247 PRINTFD(G, FB_VFont)
248 " VFontRecLoad-Debug: Added '%c' adv: %0.3f n_float: %d\n", ch[chidx], adv,
249 (int)n_float ENDFD;
250 if(ok)
251 used += n_float + 1;
252 }
253 return (ok);
254 }
255
256 #endif
257
VFontRecFree(PyMOLGlobals * G,VFontRec * I)258 static void VFontRecFree(PyMOLGlobals * G, VFontRec * I)
259 {
260 VLAFreeP(I->pen);
261 OOFreeP(I);
262 }
263
VFontInit(PyMOLGlobals * G)264 int VFontInit(PyMOLGlobals * G)
265 {
266 CVFont *I = NULL;
267 if((I = (G->VFont = pymol::calloc<CVFont>(1)))) {
268
269 CVFont *I = G->VFont;
270 I->Font = VLAlloc(VFontRec *, 10);
271 I->NFont = 0;
272 return 1;
273 } else {
274 return 0;
275 }
276 }
277
VFontFree(PyMOLGlobals * G)278 void VFontFree(PyMOLGlobals * G)
279 {
280 CVFont *I = G->VFont;
281 int a;
282 for(a = 1; a <= I->NFont; a++) {
283 VFontRecFree(G, I->Font[a]);
284 }
285 VLAFreeP(I->Font);
286 FreeP(G->VFont);
287 }
288
VFontLoad(PyMOLGlobals * G,float size,int face,int style,int can_load_new)289 int VFontLoad(PyMOLGlobals * G, float size, int face, int style, int can_load_new)
290 {
291 CVFont *I = G->VFont;
292 VFontRec *fr;
293 int a;
294 int result = 0;
295 #ifndef _PYMOL_NOPY
296 PyObject *vfont = NULL;
297 #endif
298
299 PRINTFD(G, FB_VFont)
300 " VFontLoad-Debug: Entered %f %d %d\n", size, face, style ENDFD;
301
302 for(a = 1; a <= I->NFont; a++) {
303 fr = I->Font[a];
304 if((fr->size == size) && (fr->face == face) && (fr->style == style)) {
305 result = a;
306 break;
307 }
308 }
309 if(!result) {
310 if(can_load_new) {
311 #ifndef _PYMOL_NOPY
312 vfont = PGetFontDict(G, size, face, style);
313 if(vfont) {
314 if(PyDict_Check(vfont)) {
315 #endif
316 VLACheck(I->Font, VFontRec *, I->NFont + 1);
317 fr = VFontRecNew(G);
318 #ifndef _PYMOL_NOPY
319 if(!VFontRecLoad(G, fr, vfont))
320 #else
321 if(!VFontRecLoad(G, fr))
322 #endif
323 VFontRecFree(G, fr);
324 else {
325 I->NFont++; /* always start at 1 */
326 I->Font[I->NFont] = fr;
327 result = I->NFont;
328 fr->size = size;
329 fr->face = face;
330 fr->style = style;
331 }
332 #ifndef _PYMOL_NOPY
333 }
334 Py_DECREF(vfont);
335 }
336 #endif
337 }
338 }
339 PRINTFD(G, FB_VFont)
340 " VFontLoad-Debug: Leaving with result %d (0 = failure)\n", result ENDFD;
341 return (result);
342 }
343