mirror of
https://github.com/schrodinger/pymol-open-source.git
synced 2026-06-04 20:04:21 +08:00
347 lines
8.4 KiB
C++
347 lines
8.4 KiB
C++
|
|
/*
|
|
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"MemoryDebug.h"
|
|
#include"Feedback.h"
|
|
#include"P.h"
|
|
#include"PConv.h"
|
|
#include"VFont.h"
|
|
#include "CGO.h"
|
|
|
|
#define VFONT_MASK 0xFF
|
|
|
|
struct VFontRec {
|
|
int face{};
|
|
float size{};
|
|
int style{};
|
|
ov_diff offset[VFONT_MASK + 1]{};
|
|
float advance[VFONT_MASK + 1]{};
|
|
float* pen{};
|
|
};
|
|
|
|
struct _CVFont {
|
|
VFontRec **Font;
|
|
int NFont;
|
|
};
|
|
|
|
//#ifndef _PYMOL_NOPY
|
|
static VFontRec *VFontRecNew(PyMOLGlobals * G)
|
|
{
|
|
int a;
|
|
auto I = new 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 = nullptr;
|
|
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 = nullptr;
|
|
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
|
|
/**
|
|
* @pre GIL
|
|
*/
|
|
static int VFontRecLoad(PyMOLGlobals * G, VFontRec * I, PyObject * dict)
|
|
{
|
|
assert(PyGILState_Check());
|
|
|
|
ov_diff used = 0;
|
|
int ok = true;
|
|
PyObject *key, *char_list;
|
|
PyObject *stroke_list = nullptr;
|
|
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 != nullptr);
|
|
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 != nullptr);
|
|
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);
|
|
DeleteP(I);
|
|
}
|
|
|
|
int VFontInit(PyMOLGlobals * G)
|
|
{
|
|
CVFont *I = nullptr;
|
|
if((I = (G->VFont = pymol::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 = nullptr;
|
|
#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);
|
|
}
|