layer2/VFont.cpp (303 lines of code) (raw):

/* A* ------------------------------------------------------------------- B* This file contains source code for the PyMOL computer program C* copyright 1998-2003 by Warren Lyford Delano of DeLano Scientific. D* ------------------------------------------------------------------- E* It is unlawful to modify or remove this copyright notice. F* ------------------------------------------------------------------- G* Please see the accompanying LICENSE file for further information. H* --------------------------------------------------\----------------- I* Additional authors of this source file include: -* -* -* Z* ------------------------------------------------------------------- */ #include"os_python.h" #include"os_gl.h" #include"OOMac.h" #include"MemoryDebug.h" #include"Feedback.h" #include"P.h" #include"PConv.h" #include"VFont.h" #define VFONT_MASK 0xFF typedef struct { int face; float size; int style; ov_diff offset[VFONT_MASK + 1]; float advance[VFONT_MASK + 1]; float *pen; } VFontRec; struct _CVFont { VFontRec **Font; int NFont; }; //#ifndef _PYMOL_NOPY static VFontRec *VFontRecNew(PyMOLGlobals * G) { int a; OOAlloc(G, VFontRec); for(a = 0; a <= VFONT_MASK; a++) { I->advance[a] = 0.0F; I->offset[a] = -1; } I->pen = VLAlloc(float, 1000); return (I); } //#endif int VFontWriteToCGO(PyMOLGlobals * G, int font_id, CGO * cgo, const char *text, float *pos, float *scale, float *matrix, float *color) { CVFont *I = G->VFont; VFontRec *fr = NULL; int ok = true; float base[3], pen[3]; float *pc; unsigned char c; int drawing, stroke; float *cgo_verts, *tmp_ptr; ov_diff offset; if((font_id > 0) && (font_id <= I->NFont)) { fr = I->Font[font_id]; if(fr) while(1) { c = *(text++); if(!c) break; offset = fr->offset[c]; if(offset >= 0) { pc = fr->pen + offset; copy3f(pos, base); drawing = true; stroke = false; while(drawing) { switch ((int) *(pc++)) { case -1: /* sentinel */ drawing = false; break; case 0: /* moveto */ pen[0] = (*(pc++)) * scale[0]; pen[1] = (*(pc++)) * scale[1]; pen[2] = 0.0; if(matrix) transform33f3f(matrix, pen, pen); add3f(base, pen, pen); if(stroke) { CGOEnd(cgo); } CGOBegin(cgo, GL_LINE_STRIP); if (color) CGOColorv(cgo, color); CGOVertexv(cgo, pen); stroke = true; break; case 1: /* drawto */ pen[0] = (*(pc++)) * scale[0]; pen[1] = (*(pc++)) * scale[1]; pen[2] = 0.0; if(matrix) transform33f3f(matrix, pen, pen); add3f(base, pen, pen); if(stroke) { (void)tmp_ptr; (void)cgo_verts; CGOVertexv(cgo, pen); } break; default: drawing = false; break; } } pen[0] = fr->advance[c] * scale[0]; pen[1] = 0.0; pen[2] = 0.0; if(matrix) transform33f3f(matrix, pen, pen); add3f(pen, pos, pos); if(stroke){ CGOEnd(cgo); } } } } else { PRINTFB(G, FB_VFont, FB_Errors) "VFontWriteToCGO-Error: invalid font identifier (%d)\n", font_id ENDFB(G); ok = false; } return (ok); } int VFontIndent(PyMOLGlobals * G, int font_id, const char *text, float *pos, float *scale, float *matrix, float dir) { CVFont *I = G->VFont; VFontRec *fr = NULL; int ok = true; float pen[3]; unsigned char c; ov_diff offset; if((font_id > 0) && (font_id <= I->NFont)) { fr = I->Font[font_id]; if(fr) while(1) { c = *(text++); if(!c) break; offset = fr->offset[c]; if(offset >= 0) { pen[0] = fr->advance[c] * scale[0] * dir; pen[1] = 0.0; pen[2] = 0.0; if(matrix) transform33f3f(matrix, pen, pen); add3f(pen, pos, pos); } } } else { PRINTFB(G, FB_VFont, FB_Errors) "VFontIndent-Error: invalid font identifier (%d)\n", font_id ENDFB(G); ok = false; } return (ok); } #ifndef _PYMOL_NOPY static int VFontRecLoad(PyMOLGlobals * G, VFontRec * I, PyObject * dict) { /* assumes blocked Python interpreter */ ov_diff used = 0; int ok = true; PyObject *key, *char_list; PyObject *stroke_list = NULL; Py_ssize_t pos = 0; unsigned char code[2]; float adv; ov_diff n_float; while(PyDict_Next(dict, &pos, &key, &char_list)) { if(!PConvPyStrToStr(key, (char *) code, 2)) { PRINTFB(G, FB_VFont, FB_Errors) "VFont-Error: Bad character code." ENDFB(G); ok = false; } else { if(ok) ok = (char_list != NULL); if(ok) ok = PyList_Check(char_list); if(ok) ok = (PyList_Size(char_list) >= 2); if(ok) ok = PConvPyObjectToFloat(PyList_GetItem(char_list, 0), &adv); if(ok) { stroke_list = PyList_GetItem(char_list, 1); if(ok) ok = (stroke_list != NULL); if(ok) ok = PyList_Check(stroke_list); if(ok) { n_float = PyList_Size(stroke_list); VLACheck(I->pen, float, n_float + used + 1); ok = PConvPyListToFloatArrayInPlace(stroke_list, I->pen + used, n_float); I->offset[code[0]] = used; I->advance[code[0]] = adv; I->pen[used + n_float] = -1.0F; /* sentinel */ PRINTFD(G, FB_VFont) " VFontRecLoad-Debug: Added '%c' adv: %0.3f n_float: %d\n", code[0], adv, (int)n_float ENDFD; if(ok) used += n_float + 1; } } } } return (ok); } #else #include "vfontdata.h" static int VFontRecLoad(PyMOLGlobals * G, VFontRec * I) { ov_diff used = 0; int ok = true; int chidx, n_float, i, off; float adv; for (chidx=0;chidx<VFONT_NUMBER_OF_CHARS; chidx++){ adv = advs[chidx]; n_float = n_floats[chidx]; VLACheck(I->pen, float, n_float + used + 1); off = stroke_list_place[chidx]; for (i=0;i<n_float;i++){ *(I->pen + used + i) = stroke_lists[off+i]; } I->offset[ch[chidx]] = used; I->advance[ch[chidx]] = adv; I->pen[used + n_float] = -1.0F; /* sentinel */ PRINTFD(G, FB_VFont) " VFontRecLoad-Debug: Added '%c' adv: %0.3f n_float: %d\n", ch[chidx], adv, (int)n_float ENDFD; if(ok) used += n_float + 1; } return (ok); } #endif static void VFontRecFree(PyMOLGlobals * G, VFontRec * I) { VLAFreeP(I->pen); OOFreeP(I); } int VFontInit(PyMOLGlobals * G) { CVFont *I = NULL; if((I = (G->VFont = Calloc(CVFont, 1)))) { CVFont *I = G->VFont; I->Font = VLAlloc(VFontRec *, 10); I->NFont = 0; return 1; } else { return 0; } } void VFontFree(PyMOLGlobals * G) { CVFont *I = G->VFont; int a; for(a = 1; a <= I->NFont; a++) { VFontRecFree(G, I->Font[a]); } VLAFreeP(I->Font); FreeP(G->VFont); } int VFontLoad(PyMOLGlobals * G, float size, int face, int style, int can_load_new) { CVFont *I = G->VFont; VFontRec *fr; int a; int result = 0; #ifndef _PYMOL_NOPY PyObject *vfont = NULL; #endif PRINTFD(G, FB_VFont) " VFontLoad-Debug: Entered %f %d %d\n", size, face, style ENDFD; for(a = 1; a <= I->NFont; a++) { fr = I->Font[a]; if((fr->size == size) && (fr->face == face) && (fr->style == style)) { result = a; break; } } if(!result) { if(can_load_new) { #ifndef _PYMOL_NOPY vfont = PGetFontDict(G, size, face, style); if(vfont) { if(PyDict_Check(vfont)) { #endif VLACheck(I->Font, VFontRec *, I->NFont + 1); fr = VFontRecNew(G); #ifndef _PYMOL_NOPY if(!VFontRecLoad(G, fr, vfont)) #else if(!VFontRecLoad(G, fr)) #endif VFontRecFree(G, fr); else { I->NFont++; /* always start at 1 */ I->Font[I->NFont] = fr; result = I->NFont; fr->size = size; fr->face = face; fr->style = style; } #ifndef _PYMOL_NOPY } Py_DECREF(vfont); } #endif } } PRINTFD(G, FB_VFont) " VFontLoad-Debug: Leaving with result %d (0 = failure)\n", result ENDFD; return (result); }