FontType.cpp (pymol-v2.1.0.tar.bz2) | : | FontType.cpp (pymol-open-source-2.2.0) | ||
---|---|---|---|---|
skipping to change at line 17 | skipping to change at line 17 | |||
E* It is unlawful to modify or remove this copyright notice. | E* It is unlawful to modify or remove this copyright notice. | |||
F* ------------------------------------------------------------------- | F* ------------------------------------------------------------------- | |||
G* Please see the accompanying LICENSE file for further information. | G* Please see the accompanying LICENSE file for further information. | |||
H* --------------------------------------------------\----------------- | H* --------------------------------------------------\----------------- | |||
I* Additional authors of this source file include: | I* Additional authors of this source file include: | |||
-* | -* | |||
-* | -* | |||
-* | -* | |||
Z* ------------------------------------------------------------------- | Z* ------------------------------------------------------------------- | |||
*/ | */ | |||
#include <algorithm> | ||||
#include"os_python.h" | #include"os_python.h" | |||
#include "MemoryDebug.h" | #include "MemoryDebug.h" | |||
#include "OOMac.h" | #include "OOMac.h" | |||
#include "os_gl.h" | #include "os_gl.h" | |||
#include "FontType.h" | #include "FontType.h" | |||
#include "Text.h" | #include "Text.h" | |||
#include "Ortho.h" | #include "Ortho.h" | |||
#include "Scene.h" | #include "Scene.h" | |||
#include "Character.h" | #include "Character.h" | |||
#include "Util.h" | #include "Util.h" | |||
#include "TypeFace.h" | #include "TypeFace.h" | |||
#define max2 std::max | ||||
static void CheckUnicode(unsigned int *c, int *unicnt, int *unicode){ | ||||
if(*unicnt) { | ||||
if(!(*c & 0x80)) /* corrupt UTF8 */ | ||||
*unicnt = 0; | ||||
else { | ||||
*unicode = ((*unicode) << 6) | (0x3F & *c); | ||||
(*unicnt)--; | ||||
*c = *unicode; | ||||
} | ||||
} else if(*c & 0x80) { | ||||
while(*c & 0x80) { | ||||
*c = (*c << 1) & 0xFF; | ||||
(*unicnt)++; | ||||
} | ||||
*unicode = (*c >> ((*unicnt)--)); | ||||
} | ||||
} | ||||
static void GenerateCharFngrprnt(PyMOLGlobals *G, CharFngrprnt *fprnt, unsigned | ||||
int c, int TextID, float size, int sampling, short no_flat, int flat){ | ||||
unsigned char *rgba; | ||||
UtilZeroMem(fprnt, sizeof(CharFngrprnt)); | ||||
fprnt->u.i.text_id = TextID; | ||||
fprnt->u.i.size = (int) (size * 64 * sampling); | ||||
rgba = fprnt->u.i.color; | ||||
if (!TextGetIsPicking(G)){ | ||||
TextGetColorUChar(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
rgba = fprnt->u.i.outline_color; | ||||
if (no_flat || !flat){ | ||||
TextGetOutlineColor(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
} else if(flat) { | ||||
TextGetColorUChar(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
} | ||||
} | ||||
fprnt->u.i.ch = c; | ||||
fprnt->u.i.flat = flat; | ||||
} | ||||
typedef struct { | typedef struct { | |||
CFont Font; /* must be first */ | CFont Font; /* must be first */ | |||
PyMOLGlobals *G; | PyMOLGlobals *G; | |||
CTypeFace *TypeFace; | CTypeFace *TypeFace; | |||
} CFontType; | } CFontType; | |||
#ifdef _PYMOL_INLINE | #ifdef _PYMOL_INLINE | |||
__inline__ | __inline__ | |||
#endif | #endif | |||
static const char *_FontTypeRenderOpenGL(RenderInfo * info, | static const char *_FontTypeRenderOpenGL(RenderInfo * info, | |||
CFontType * I, const char *st, | CFontType * I, const char *st, | |||
float size, int flat, float *rpos SHADERCGOAR G) | float size, int flat, float *rpos, short need Size, short relativeMode, short shouldRender SHADERCGOARG) | |||
{ | { | |||
PyMOLGlobals *G = I->Font.G; | PyMOLGlobals *G = I->Font.G; | |||
if(G->ValidContext) { | if(G->ValidContext) { | |||
unsigned int c; | unsigned int c; | |||
int pushed = OrthoGetPushed(G); | int pushed = OrthoGetPushed(G); | |||
int kern_flag = false; | int kern_flag = false; | |||
unsigned int last_c = 0; | unsigned int last_c = 0; | |||
int sampling = 1; | int sampling = 1; | |||
const float _0 = 0.0F, _1 = 1.0F, _m1 = -1.0F; | const float _0 = 0.0F, _1 = 1.0F, _m1 = -1.0F; | |||
float x_indent = 0.0F, y_indent = 0.0F, z_indent = 0.0F; | float x_indent = 0.0F, y_indent = 0.0F, z_indent = 0.0F; | |||
float text_width = 0.f; | float text_width = 0.f, line_width = 0.f, tot_text_width; | |||
float text_just = 1.f - TextGetJustification(G); | ||||
float text_spacing = TextGetSpacing(G); | ||||
float text_buffer[2]; | ||||
int unicode = 0; | int unicode = 0; | |||
int unicnt = 0; | int unicnt = 0; | |||
int nlines = countchrs(st, '\n') + 1; | ||||
int linenum = 0; | ||||
short cont = 0; | ||||
float descender = TypeFaceGetDescender(I->TypeFace) / 2.f; | ||||
float v_scale = SceneGetScreenVertexScale(G, NULL); | ||||
copy2f(TextGetLabelBuffer(G), text_buffer); | ||||
sampling = info->sampling; | sampling = info->sampling; | |||
if(st && (*st)) { | if(st && (*st)) { | |||
float v_scale; | float *line_widths = NULL; | |||
float screenWorldOffset[3] = { 0.0F, 0.0F, 0.0F }; | float screenWorldOffset[3] = { 0.0F, 0.0F, 0.0F }; | |||
float tot_height; | ||||
v_scale = SceneGetScreenVertexScale(G, NULL); | if (nlines>1){ | |||
line_widths = Calloc(float, nlines); | ||||
} | ||||
if(size < _0) { | if(size < _0) { | |||
size = (int) (0.5F - size / v_scale); | size = (int) (0.5F - size / v_scale); | |||
if (size <= 0) | if (size <= 0) | |||
size = 1; | size = 1; | |||
} else { | } else { | |||
size = DIP2PIXEL(size); | size = DIP2PIXEL(size); | |||
} | } | |||
text_buffer[0] *= size; | ||||
text_buffer[1] *= size; | ||||
if(rpos) { | if(rpos) { | |||
if(rpos[0] < _1) { /* we need to measure the string width before st | TextSetIndentFactorX(G, rpos[0] < _m1 ? _m1 : rpos[0] > 1.f ? 1.f : rpos[ | |||
arting to draw */ | 0]); | |||
TextSetIndentFactorY(G, rpos[1] < _m1 ? _m1 : rpos[1] > 1.f ? 1.f : rpos[ | ||||
1]); | ||||
if(needSize || rpos[0] < _1) { /* we need to measure the string wid | ||||
th before starting to draw */ | ||||
const char *sst = st; | const char *sst = st; | |||
while((c = *(sst++))) { | while((c = *(sst++))) { | |||
if(unicnt) { | if (c == '\n'){ | |||
if(!(c & 0x80)) /* corrupt UTF8 */ | line_widths[linenum] = line_width; | |||
unicnt = 0; | text_width = max2(text_width, line_width); | |||
else { | line_width = 0.f; | |||
unicode = (unicode << 6) | (0x3F & c); | linenum++; | |||
unicnt--; | continue; | |||
c = unicode; | } | |||
} | CheckUnicode(&c, &unicnt, &unicode); | |||
} else if(c & 0x80) { | ||||
while(c & 0x80) { | ||||
c = (c << 1) & 0xFF; | ||||
unicnt++; | ||||
} | ||||
unicode = (c >> (unicnt--)); | ||||
} | ||||
if(!unicnt) { | if(!unicnt) { | |||
CharFngrprnt fprnt; | CharFngrprnt fprnt; | |||
unsigned char *rgba; | GenerateCharFngrprnt(G, &fprnt, c, I->Font.TextID, size, sampling, | |||
UtilZeroMem(&fprnt, sizeof(fprnt)); | 0, flat); | |||
fprnt.u.i.text_id = I->Font.TextID; | ||||
fprnt.u.i.size = (int) (size * 64 * sampling); | ||||
rgba = fprnt.u.i.color; | ||||
TextGetColorUChar(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
rgba = fprnt.u.i.outline_color; | ||||
if(!flat) { | ||||
TextGetOutlineColor(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
} else { | ||||
TextGetColorUChar(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
} | ||||
fprnt.u.i.ch = c; | ||||
fprnt.u.i.flat = flat; | ||||
{ | { | |||
int id = CharacterFind(G, &fprnt); | int id = CharacterFind(G, &fprnt); | |||
if(!id) { | if(!id) { | |||
id = TypeFaceCharacterNew(I->TypeFace, &fprnt, size * sampling ); | id = TypeFaceCharacterNew(I->TypeFace, &fprnt, size * sampling ); | |||
} | } | |||
if(id) { | if(id) { | |||
if(kern_flag) { | if(kern_flag) { | |||
text_width += (TypeFaceGetKerning(I->TypeFace, | line_width += (TypeFaceGetKerning(I->TypeFace, | |||
last_c, c, size) / sampling); | last_c, c, size) / sampling); | |||
} | } | |||
text_width += CharacterGetAdvance(G, sampling, id); | line_width += CharacterGetAdvance(G, sampling, id); | |||
} | } | |||
} | } | |||
kern_flag = true; | kern_flag = true; | |||
last_c = c; | last_c = c; | |||
} | } | |||
} | } | |||
if (line_widths) | ||||
line_widths[linenum] = line_width; | ||||
text_width = max2(text_width, line_width) ; | ||||
tot_text_width = text_width + 2.f * text_buffer[0]; | ||||
TextSetWidth(G, tot_text_width); | ||||
tot_height = pymol_roundf(size * (nlines + (nlines-1) * (text_spacing-1 | ||||
.f)) + 2.f * text_buffer[1]); | ||||
TextSetHeight(G, tot_height); | ||||
{ | { | |||
float factor = rpos[0] / 2.0F - 0.5F; | float factor = rpos[0] / 2.0F - 0.5F; | |||
/* if -1. < rpos[0] < 1. , then we need to determine the label's widt h | /* if -1. < rpos[0] < 1. , then we need to determine the label's widt h | |||
so that we can justify it appropriately */ | so that we can justify it appropriately */ | |||
if(factor < _m1) // if rpos[0] < -1., right justified | // if rpos[0] < -1., right justified | |||
factor = -_1; | // if rpos[0] > 1., left justified, label width not needed | |||
if(factor > _0) // if rpos[0] > 1., left justified, label width not | factor = (factor < _m1) ? _m1 : (factor > _0) ? _0 : factor; | |||
needed | x_indent -= factor * tot_text_width; | |||
factor = _0; | ||||
x_indent -= factor * text_width; | ||||
} | } | |||
} | } | |||
/* if label_position x is -1 to 1, the label is placed in x such that | /* if label_position x is -1 to 1, the label is placed in x such that | |||
0 - centered | 0 - centered | |||
-1 - right justified on projected point | -1 - right justified on projected point | |||
1 - left justified on projected point | 1 - left justified on projected point | |||
*/ | */ | |||
if(rpos[0] < _m1) { | if(rpos[0] < _m1) { | |||
screenWorldOffset[0] -= (rpos[0] + _1);// / v_scale; | screenWorldOffset[0] -= (rpos[0] + _1); | |||
} else if(rpos[0] > _1) { | } else if(rpos[0] > _1) { | |||
screenWorldOffset[0] -= (rpos[0] - _1);// / v_scale; | screenWorldOffset[0] -= (rpos[0] - _1); | |||
} | } | |||
if(rpos[1] < _1) { | if(rpos[1] < _1) { | |||
float factor = -rpos[1] / 2.0F + 0.5F; | float factor = -rpos[1] / 2.0F + 0.5F; | |||
if(factor > _1) | factor = (factor > _1) ? _1 : (factor < _0) ? _0 : factor; | |||
factor = _1; | y_indent = pymol_roundf((size * factor) * (1.f + text_spacing * max2(0. | |||
if(factor < _0) | f, nlines-1.f))); | |||
factor = _0; | } | |||
y_indent = 0.75 * size * factor; | { | |||
float factor = rpos[1]; | ||||
factor = (factor > _1) ? _1 : (factor < _m1) ? _m1 : factor; | ||||
y_indent -= pymol_roundf(factor * text_buffer[1]); | ||||
} | } | |||
if(rpos[1] < _m1) { | if(rpos[1] < _m1) { | |||
screenWorldOffset[1] -= (rpos[1] + _1); | screenWorldOffset[1] -= (rpos[1] + _1); | |||
} else if(rpos[1] > _1) { | } else if(rpos[1] > _1) { | |||
screenWorldOffset[1] -= (rpos[1] - _1); | screenWorldOffset[1] -= (rpos[1] - _1); | |||
} | } | |||
/* leave room for fonts of finite depth */ | /* leave room for fonts of finite depth */ | |||
z_indent = (rpos[2] < _m1) ? (rpos[2]+1.f) : (rpos[2] > 1.f) ? (rpos[2]-1 .f) : 0.f; | z_indent = (rpos[2] < _m1) ? (rpos[2]+1.f) : (rpos[2] > 1.f) ? (rpos[2]-1 .f) : 0.f; | |||
if (!shaderCGO){ | if (!shaderCGO){ | |||
x_indent += screenWorldOffset[0] / v_scale; | x_indent += screenWorldOffset[0] / v_scale; | |||
y_indent += screenWorldOffset[1] / v_scale; | y_indent += pymol_roundf(screenWorldOffset[1] / v_scale); | |||
} | } | |||
screenWorldOffset[2] += z_indent; // need to take into account weird -1 t o 1, and sub 1 from abs val | screenWorldOffset[2] += z_indent; // need to take into account weird -1 t o 1, and sub 1 from abs val | |||
} | } | |||
if(!pushed) { | if(!pushed) { | |||
float *v = TextGetPos(G); | float *v = TextGetPos(G); | |||
float loc[3]; | float loc[3]; | |||
float zero[3] = { 0.0F, 0.0F, 0.0F }; | float zero[3] = { 0.0F, 0.0F, 0.0F }; | |||
TextSetScreenWorldOffset(G, screenWorldOffset); | TextSetScreenWorldOffset(G, screenWorldOffset); | |||
TextSetWorldPos(G, v); | TextSetWorldPos(G, v); | |||
if(rpos) { | if(rpos) { | |||
if(info->ortho) { | if(info->ortho) { | |||
float orig[3]; | float orig[3]; | |||
SceneOriginGet(G, orig); | SceneOriginGet(G, orig); | |||
SceneGetEyeNormal(G, orig, loc); | SceneGetEyeNormal(G, orig, loc); | |||
} else { | } else { | |||
SceneGetEyeNormal(G, v, loc); | SceneGetEyeNormal(G, v, loc); | |||
} | } | |||
scale3f(loc, z_indent, loc); | scale3f(loc, z_indent, loc); | |||
add3f(v, loc, loc); | add3f(v, loc, loc); | |||
v = loc; | v = loc; | |||
} | } | |||
if (!shaderCGO){ | ||||
unsigned char posIsSet = TextGetLabelPosIsSet(G); | ||||
switch (posIsSet){ | ||||
case 1: | ||||
SceneAdjustZtoScreenZ(G, v, TextGetLabelPos(G)[0]); | ||||
break; | ||||
case 2: | ||||
SceneSetPointToWorldScreenRelative(G, v, TextGetLabelPos(G)); | ||||
break; | ||||
} | ||||
} | ||||
TextSetLabelPushPos(G, v); | ||||
if (!shouldRender) | ||||
return st; | ||||
ScenePushRasterMatrix(G, v); | ScenePushRasterMatrix(G, v); | |||
TextSetPos(G, zero); | TextSetPos(G, zero); | |||
#ifndef PURE_OPENGL_ES_2 | ||||
} else { | ||||
#endif | ||||
if (!shouldRender) | ||||
return st; | ||||
} | } | |||
if(rpos) { | if(rpos) { | |||
// float ax = x_indent * v_scale, ay = y_indent * v_scale; | ||||
// printf("x_indent=%f y_indent=%f ax=%f ay=%f v_scale=%f rpos=%f %f | ||||
%f\n", x_indent, y_indent, ax, ay, v_scale, rpos[0], rpos[1], rpos[2]); | ||||
TextIndent(G, x_indent, y_indent); | TextIndent(G, x_indent, y_indent); | |||
} | } | |||
CharacterRenderOpenGLPrime(G, info); | CharacterRenderOpenGLPrime(G, info); | |||
while((c = *(st++))) { | kern_flag = false; | |||
if(unicnt) { | TextGetPos(G)[1] += (int)pymol_roundf(size * (text_spacing * (nlines-1) + | |||
if(!(c & 0x80)) /* corrupt UTF8 */ | descender)); | |||
unicnt = 0; | if (line_widths){ | |||
else { | TextGetPos(G)[0] += text_just * (text_width - line_widths[0])/2.f; | |||
unicode = (unicode << 6) | (0x3F & c); | } | |||
unicnt--; | TextGetPos(G)[0] += text_buffer[0]; | |||
c = unicode; | linenum = 0; | |||
} | cont = 1; | |||
} else if(c & 0x80) { | while(cont && (c = *(st++))) { | |||
while(c & 0x80) { | if (c == '\n'){ | |||
c = (c << 1) & 0xFF; | float zero[3] = { 0.0F, 0.0F, 0.0F }; | |||
unicnt++; | TextSetPos(G, zero); | |||
} | if (rpos){ | |||
unicode = (c >> (unicnt--)); | TextIndent(G, x_indent, y_indent); | |||
} | } | |||
linenum++; | ||||
TextGetPos(G)[1] += (int)pymol_roundf(size * (text_spacing * (nlines - | ||||
1 - linenum) + descender)); | ||||
if (line_widths) | ||||
TextGetPos(G)[0] += text_just * (text_width - line_widths[linenum])/2 | ||||
.f + text_buffer[0]; | ||||
kern_flag = false; | ||||
continue; | ||||
} | ||||
CheckUnicode(&c, &unicnt, &unicode); | ||||
if(!unicnt) { | if(!unicnt) { | |||
CharFngrprnt fprnt; | CharFngrprnt fprnt; | |||
unsigned char *rgba; | GenerateCharFngrprnt(G, &fprnt, c, I->Font.TextID, size, sampling, 1, f | |||
UtilZeroMem(&fprnt, sizeof(fprnt)); | lat); | |||
fprnt.u.i.text_id = I->Font.TextID; | ||||
fprnt.u.i.size = (int) (size * 64 * sampling); | ||||
rgba = fprnt.u.i.color; | ||||
TextGetColorUChar(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
rgba = fprnt.u.i.outline_color; | ||||
TextGetOutlineColor(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
fprnt.u.i.ch = c; | ||||
fprnt.u.i.flat = flat; | ||||
{ | { | |||
int id = CharacterFind(G, &fprnt); | int id = CharacterFind(G, &fprnt); | |||
if(!id) { | if(!id) { | |||
id = TypeFaceCharacterNew(I->TypeFace, &fprnt, size * sampling); | id = TypeFaceCharacterNew(I->TypeFace, &fprnt, size * sampling); | |||
} | } | |||
if(id) { | if(id) { | |||
if(kern_flag) { | if(kern_flag) { | |||
TextAdvance(G, TypeFaceGetKerning(I->TypeFace, | TextAdvance(G, TypeFaceGetKerning(I->TypeFace, | |||
last_c, c, size) / sampling); | last_c, c, size) / sampling); | |||
} | } | |||
CharacterRenderOpenGL(G, info, id, true SHADERCGOARGVAR); /* handles advance */ | cont &= CharacterRenderOpenGL(G, info, id, true, relativeMode SHAD ERCGOARGVAR); /* handles advance */ | |||
} | } | |||
} | } | |||
kern_flag = true; | kern_flag = true; | |||
last_c = c; | last_c = c; | |||
} | } | |||
} | } | |||
CharacterRenderOpenGLDone(G, info); | CharacterRenderOpenGLDone(G, info); | |||
if(!pushed) { | if(!pushed) { | |||
ScenePopRasterMatrix(G); | ScenePopRasterMatrix(G); | |||
} | } | |||
FreeP(line_widths); | ||||
} | } | |||
if (!cont) | ||||
return st; | ||||
} | } | |||
return st; | return st; | |||
} | } | |||
static const char *FontTypeRenderOpenGL(RenderInfo * info, CFontType * I, const char *st, float size, | static const char *FontTypeRenderOpenGL(RenderInfo * info, CFontType * I, const char *st, float size, | |||
float *rpos SHADERCGOARG) | float *rpos, short needSize, short relativeMod e, short shouldRender SHADERCGOARG) | |||
{ | { | |||
return _FontTypeRenderOpenGL(info, I, st, size, false, rpos SHADERCGOARGVAR); | return _FontTypeRenderOpenGL(info, I, st, size, false, rpos, needSize, relativ eMode, shouldRender SHADERCGOARGVAR); | |||
} | } | |||
static const char *FontTypeRenderOpenGLFlat(RenderInfo * info, CFontType * I, co nst char *st, | static const char *FontTypeRenderOpenGLFlat(RenderInfo * info, CFontType * I, co nst char *st, | |||
float size, float *rpos SHADERCGOARG) | float size, float *rpos, short needSize, s hort relativeMode, short shouldRender SHADERCGOARG) | |||
{ | { | |||
return _FontTypeRenderOpenGL(info, I, st, size, true, rpos SHADERCGOARGVAR); | return _FontTypeRenderOpenGL(info, I, st, size, true, rpos, needSize, relative Mode, shouldRender SHADERCGOARGVAR); | |||
} | } | |||
static const char *FontTypeRenderRay(CRay * ray, CFontType * I, const char *st, float size, | static const char *FontTypeRenderRay(CRay * ray, CFontType * I, const char *st, float size, | |||
float *rpos) | float *rpos, short needSize, short relativeMode) | |||
{ | { | |||
PyMOLGlobals *G = I->Font.G; | PyMOLGlobals *G = I->Font.G; | |||
unsigned int c; | unsigned int c; | |||
int kern_flag = false; | int kern_flag = false; | |||
unsigned int last_c = 0; | unsigned int last_c = 0; | |||
int sampling = ray->Sampling; | int sampling = ray->Sampling; | |||
const float _0 = 0.0F, _1 = 1.0F, _m1 = -1.0F; | const float _0 = 0.0F, _1 = 1.0F, _m1 = -1.0F; | |||
float x_indent = 0.0F, y_indent = 0.0F, z_indent = 0.0F; | float x_indent = 0.0F, y_indent = 0.0F, z_indent = 0.0F; | |||
float text_width = 0.f, line_width = 0.f, tot_text_width; | ||||
float text_just = 1.f - TextGetJustification(G); | ||||
float text_spacing = TextGetSpacing(G); | ||||
float text_buffer[2]; | ||||
float xn[3], yn[3], x_adj[3], y_adj[3], pos[3], *v; | float xn[3], yn[3], x_adj[3], y_adj[3], pos[3], *v; | |||
int unicode = 0; | int unicode = 0; | |||
int unicnt = 0; | int unicnt = 0; | |||
int nlines = countchrs(st, '\n') + 1; | ||||
int linenum = 0; | ||||
float descender = TypeFaceGetDescender(I->TypeFace); | ||||
float v_scale = SceneGetScreenVertexScale(G, NULL); | ||||
copy2f(TextGetLabelBuffer(G), text_buffer); | ||||
if(st && (*st)) { | if(st && (*st)) { | |||
float v_scale = SceneGetScreenVertexScale(G, NULL); | float origpos[3]; | |||
float *line_widths = NULL; | ||||
float tot_height; | ||||
if (nlines>1){ | ||||
line_widths = Calloc(float, nlines); | ||||
} | ||||
if(size < _0) { | ||||
size = (int) (0.5F - size / v_scale); | ||||
} else { | ||||
size = DIP2PIXEL(size); | ||||
} | ||||
text_buffer[0] *= size; | ||||
text_buffer[1] *= size; | ||||
if(rpos) { | if(rpos) { | |||
float loc[3]; | float loc[3]; | |||
/* leave room for fonts of finite depth */ | /* leave room for fonts of finite depth */ | |||
z_indent = (rpos[2] < _m1) ? (rpos[2]+1.f) : (rpos[2] > 1.f) ? (rpos[2]-1. f) : 0.f; | z_indent = (rpos[2] < _m1) ? (rpos[2]+1.f) : (rpos[2] > 1.f) ? (rpos[2]-1. f) : 0.f; | |||
v = TextGetPos(I->G); | v = TextGetPos(I->G); | |||
if(ray->Ortho) { | if(ray->Ortho) { | |||
float orig[3]; | float orig[3]; | |||
SceneOriginGet(G, orig); | SceneOriginGet(G, orig); | |||
SceneGetEyeNormal(G, orig, loc); | SceneGetEyeNormal(G, orig, loc); | |||
} else { | } else { | |||
SceneGetEyeNormal(G, v, loc); | SceneGetEyeNormal(G, v, loc); | |||
} | } | |||
scale3f(loc, z_indent, loc); | scale3f(loc, z_indent, loc); | |||
add3f(v, loc, loc); | add3f(v, loc, loc); | |||
{ | ||||
unsigned char posIsSet = TextGetLabelPosIsSet(G); | ||||
switch (posIsSet){ | ||||
case 1: | ||||
RayAdjustZtoScreenZ(ray, loc, TextGetLabelPos(G)[0]); | ||||
break; | ||||
case 2: | ||||
RaySetPointToWorldScreenRelative(ray, loc, TextGetLabelPos(G)); | ||||
break; | ||||
} | ||||
} | ||||
TextSetLabelPushPos(G, loc); | ||||
TextSetPos(I->G, loc); | TextSetPos(I->G, loc); | |||
} | } | |||
RayGetScaledAxes(ray, xn, yn); | RayGetScaledAxes(ray, xn, yn); | |||
if(size < _0) { | ||||
size = (int) (0.5F - size / v_scale); | ||||
} else { | ||||
size = DIP2PIXEL(size); | ||||
} | ||||
if(rpos) { | if(rpos) { | |||
if(needSize || rpos[0] < _1) { /* we need to measure the string wid | ||||
if(rpos[0] < _1) { /* we need to measure the string width before st | th before starting to draw */ | |||
arting to draw */ | ||||
float factor = rpos[0] / 2.0F - 0.5F; | float factor = rpos[0] / 2.0F - 0.5F; | |||
const char *sst = st; | const char *sst = st; | |||
float max_x_indent = 0.f; | ||||
// factor -1 to 0 based on justification (i.e., rpos[0]) | ||||
factor = (factor < _m1) ? _m1 : (factor > _0) ? _0 : factor; | factor = (factor < _m1) ? _m1 : (factor > _0) ? _0 : factor; | |||
while((c = *(sst++))) { | while((c = *(sst++))) { | |||
if(unicnt) { | if (c == '\n'){ | |||
if(!(c & 0x80)) /* corrupt UTF8 */ | text_width = max2(text_width, line_width); | |||
unicnt = 0; | line_widths[linenum] = line_width; | |||
else { | line_width = 0.f; | |||
unicode = (unicode << 6) | (0x3F & c); | kern_flag = false; | |||
unicnt--; | linenum++; | |||
c = unicode; | max_x_indent = max2(x_indent, max_x_indent); | |||
} | x_indent = 0.f; | |||
} else if(c & 0x80) { | continue; | |||
while(c & 0x80) { | } | |||
c = (c << 1) & 0xFF; | CheckUnicode(&c, &unicnt, &unicode); | |||
unicnt++; | ||||
} | ||||
unicode = (c >> (unicnt--)); | ||||
} | ||||
if(!unicnt) { | if(!unicnt) { | |||
CharFngrprnt fprnt; | CharFngrprnt fprnt; | |||
unsigned char *rgba; | GenerateCharFngrprnt(G, &fprnt, c, I->Font.TextID, size, sampling, 1, | |||
UtilZeroMem(&fprnt, sizeof(fprnt)); | 0 /* flat is not set */); | |||
fprnt.u.i.text_id = I->Font.TextID; | ||||
fprnt.u.i.size = (int) (size * 64 * sampling); | ||||
rgba = fprnt.u.i.color; | ||||
TextGetColorUChar(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
rgba = fprnt.u.i.outline_color; | ||||
TextGetOutlineColor(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
fprnt.u.i.ch = c; | ||||
{ | { | |||
int id = CharacterFind(G, &fprnt); | int id = CharacterFind(G, &fprnt); | |||
if(!id) { | if(!id) { | |||
id = TypeFaceCharacterNew(I->TypeFace, &fprnt, size * sampling); | id = TypeFaceCharacterNew(I->TypeFace, &fprnt, size * sampling); | |||
} | } | |||
if(id) { | if(id) { | |||
float adv; | ||||
if(kern_flag) { | if(kern_flag) { | |||
x_indent -= factor * TypeFaceGetKerning(I->TypeFace, | float kern = TypeFaceGetKerning(I->TypeFace, | |||
last_c, | last_c, | |||
c, size * sampling) / | c, size * sampling) ; | |||
sampling; | line_width += kern; | |||
x_indent -= factor * kern; | ||||
} | } | |||
x_indent -= factor * CharacterGetAdvance(G, 1, id); | adv = CharacterGetAdvance(G, 1, id); | |||
line_width += adv; | ||||
x_indent -= factor * adv; | ||||
kern_flag = true; | kern_flag = true; | |||
last_c = c; | last_c = c; | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
max_x_indent = max2(x_indent, max_x_indent); | ||||
x_indent = max_x_indent; | ||||
} | } | |||
text_width = max2(text_width, line_width); | ||||
tot_text_width = text_width + 2.f * text_buffer[0] * sampling; | ||||
if (line_widths) | ||||
line_widths[linenum] = line_width; | ||||
TextSetWidth(G, tot_text_width/(float)sampling); | ||||
tot_height = size * (nlines + (nlines-1) * (text_spacing-1.f)) + 2.f * tex | ||||
t_buffer[1]; | ||||
TextSetHeight(G, tot_height); | ||||
if(rpos[0] < _m1) { | if(rpos[0] < _m1) { | |||
x_indent -= 2 * (rpos[0] + _1) / v_scale; | x_indent -= 2 * (rpos[0] + _1) / v_scale; | |||
} else if(rpos[0] > _1) { | } else if(rpos[0] > _1) { | |||
x_indent -= 2 * (rpos[0] - _1) / v_scale; | x_indent -= 2 * (rpos[0] - _1) / v_scale; | |||
} | } | |||
if(rpos[1] < _1) { | if(rpos[1] < _1) { | |||
float factor = -rpos[1] / 2.0F + 0.5F; | float factor = -rpos[1] / 2.0F + 0.5F; | |||
if(factor > _1) | factor = (factor > _1) ? _1 : (factor < _0) ? _0 : factor; | |||
factor = _1; | y_indent = (sampling * size * factor) * (1.f + text_spacing * max2(0.f, n | |||
if(factor < _0) | lines-1.f)); | |||
factor = _0; | } | |||
y_indent = 0.75F * sampling * size * factor; | { | |||
float factor = rpos[1]; | ||||
factor = (factor > _1) ? _1 : (factor < _m1) ? _m1 : factor; | ||||
y_indent -= factor * sampling * text_buffer[1]; | ||||
} | } | |||
if(rpos[1] < _m1) { | if(rpos[1] < _m1) { | |||
y_indent -= 2 * (rpos[1] + _1) / v_scale; | y_indent -= 2 * (rpos[1] + _1) / v_scale; | |||
} else if(rpos[1] > _1) { | } else if(rpos[1] > _1) { | |||
y_indent -= 2 * (rpos[1] - _1) / v_scale; | y_indent -= 2 * (rpos[1] - _1) / v_scale; | |||
} | } | |||
v = TextGetPos(I->G); | v = TextGetPos(I->G); | |||
if (line_widths){ | ||||
x_indent -= text_just * (text_width - line_widths[0])/2.f; | ||||
} | ||||
{ | ||||
float factor = rpos[0]; | ||||
factor = (factor > _1) ? _1 : (factor < _m1) ? _m1 : factor; | ||||
x_indent -= factor * sampling * text_buffer[0]; | ||||
} | ||||
scale3f(xn, x_indent, x_adj); | scale3f(xn, x_indent, x_adj); | |||
scale3f(yn, y_indent, y_adj); | scale3f(yn, y_indent - size * (sampling * text_spacing * (nlines-1) + desc ender), y_adj); | |||
subtract3f(v, x_adj, pos); | subtract3f(v, x_adj, pos); | |||
subtract3f(pos, y_adj, pos); | subtract3f(pos, y_adj, pos); | |||
TextSetPos(I->G, pos); | TextSetPos(I->G, pos); | |||
} | } | |||
kern_flag = false; | kern_flag = false; | |||
copy3f(TextGetPos(I->G), origpos); | ||||
linenum = 0; | ||||
while((c = *(st++))) { | while((c = *(st++))) { | |||
if(unicnt) { | if (c == '\n'){ | |||
if(!(c & 0x80)) /* corrupt UTF8 */ | copy3f(origpos, TextGetPos(I->G)); | |||
unicnt = 0; | kern_flag = false; | |||
else { | linenum++; | |||
unicode = (unicode << 6) | (0x3F & c); | scale3f(yn, pymol_roundf(text_spacing * size * linenum * sampling), y_adj | |||
unicnt--; | ); // need to round to pixel in y | |||
c = unicode; | subtract3f(TextGetPos(G), y_adj, TextGetPos(G)); | |||
} | if (line_widths){ | |||
} else if(c & 0x80) { | scale3f(xn, text_just * (line_widths[0] - line_widths[linenum])/2.f, x_ | |||
while(c & 0x80) { | adj); | |||
c = (c << 1) & 0xFF; | add3f(TextGetPos(G), x_adj, TextGetPos(G)); | |||
unicnt++; | } | |||
} | kern_flag = false; | |||
unicode = (c >> (unicnt--)); | continue; | |||
} | } | |||
CheckUnicode(&c, &unicnt, &unicode); | ||||
if(!unicnt) { | if(!unicnt) { | |||
CharFngrprnt fprnt; | CharFngrprnt fprnt; | |||
unsigned char *rgba; | GenerateCharFngrprnt(G, &fprnt, c, I->Font.TextID, size, sampling, 0, 0); | |||
UtilZeroMem(&fprnt, sizeof(fprnt)); | ||||
fprnt.u.i.text_id = I->Font.TextID; | ||||
fprnt.u.i.size = (int) (size * 64 * sampling); | ||||
rgba = fprnt.u.i.color; | ||||
TextGetColorUChar(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
rgba = fprnt.u.i.outline_color; | ||||
TextGetOutlineColor(G, rgba, rgba + 1, rgba + 2, rgba + 3); | ||||
fprnt.u.i.ch = c; | ||||
{ | { | |||
int id = CharacterFind(G, &fprnt); | int id = CharacterFind(G, &fprnt); | |||
if(!id) { | if(!id) { | |||
id = TypeFaceCharacterNew(I->TypeFace, &fprnt, size * sampling); | id = TypeFaceCharacterNew(I->TypeFace, &fprnt, size * sampling); | |||
} | } | |||
if(id) { | if(id) { | |||
if(kern_flag) { | if(kern_flag) { | |||
float kern = TypeFaceGetKerning(I->TypeFace, | float kern = TypeFaceGetKerning(I->TypeFace, | |||
last_c, | last_c, | |||
c, | c, | |||
size * sampling) / sampling; | size * sampling); | |||
v = TextGetPos(I->G); | v = TextGetPos(I->G); | |||
scale3f(xn, kern, x_adj); | scale3f(xn, kern, x_adj); | |||
add3f(v, x_adj, pos); | add3f(v, x_adj, pos); | |||
TextSetPos(I->G, pos); | TextSetPos(I->G, pos); | |||
} | } | |||
ray->character(id); /* handles advance */ | ray->character(id); /* handles advance */ | |||
kern_flag = true; | kern_flag = true; | |||
last_c = c; | last_c = c; | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
FreeP(line_widths); | ||||
} | } | |||
return st; | return st; | |||
} | } | |||
static void FontTypeFree(CFont * font) | static void FontTypeFree(CFont * font) | |||
{ | { | |||
CFontType *I = (CFontType *) font; | CFontType *I = (CFontType *) font; | |||
TypeFaceFree(I->TypeFace); | TypeFaceFree(I->TypeFace); | |||
OOFreeP(I); | OOFreeP(I); | |||
} | } | |||
End of changes. 58 change blocks. | ||||
162 lines changed or deleted | 271 lines changed or added |