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