Logo Search packages:      
Sourcecode: pymol version File versions  Download package

FontType.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 "MemoryDebug.h"
#include "OOMac.h"
#include "os_gl.h"
#include "FontType.h"
#include "Text.h"
#include "Ortho.h"
#include "Scene.h"
#include "Character.h"
#include "Util.h"
#include "TypeFace.h"

typedef struct {
  CFont Font; /* must be first */
  PyMOLGlobals *G;
  CTypeFace *TypeFace;
} CFontType;


#ifdef _PYMOL_INLINE
__inline__ 
#endif
static char *_FontTypeRenderOpenGL(RenderInfo *info, 
                                              CFontType *I,char *st,
                                              float size,int flat, float *rpos)
{
  register PyMOLGlobals *G = I->Font.G;
  if(G->ValidContext) {
    unsigned int c;
    int pushed = OrthoGetPushed(G);
    int kern_flag = false;
    unsigned int last_c = 0;
    int sampling = 1;
    const float _0 = 0.0F, _1 = 1.0F, _m1 = -1.0F;
    float x_indent=0.0F, y_indent=0.0F, z_indent = 0.0F;
    int unicode = 0;
    int unicnt = 0;

    sampling = info->sampling;
    if(st&&(*st)) {
      float origin[3], v_scale;
      SceneOriginGet(G,origin);
      v_scale = SceneGetScreenVertexScale(G,origin);

      if(size<_0) {
        size = (int)(0.5F-size/v_scale);
      }

      if(rpos) {
        if(rpos[0]<_1) { /* we need to measure the string width before starting to draw */
          float factor = rpos[0]/2.0F - 0.5F;
          char *sst = st;
          if(factor<_m1) factor = -_1;
          if(factor>_0) factor = _0;
          while((c=*(sst++))) {
            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--));
            }
            if(!unicnt) {
              CharFngrprnt fprnt;
              unsigned char *rgba;
              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;
              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);
                if(!id) {
                  id = TypeFaceCharacterNew(I->TypeFace,&fprnt,size*sampling);
                }
                if(id) {
                  if(kern_flag) {
                    x_indent -= factor * (TypeFaceGetKerning(I->TypeFace, 
                                                             last_c,
                                                             c,
                                                             size)/sampling);
                  }
                  x_indent -= factor * CharacterGetAdvance(G,sampling,id);
                }
              }
              kern_flag = true;
              last_c = c;
            }
          }
        }
        if(rpos[0]<_m1) {
          x_indent -= (rpos[0]+_1)/v_scale;
        } else if(rpos[0]>_1) {
          x_indent -= (rpos[0]-_1)/v_scale;
        }
        if(rpos[1]<_1) {
          float factor = -rpos[1]/2.0F + 0.5F;
          if(factor>_1) factor = _1;
          if(factor<_0) factor = _0;
          y_indent = 0.75*size*factor;
        }
        if(rpos[1]<_m1) {
          y_indent -= (rpos[1]+_1)/v_scale;
        } else if(rpos[1]>_1) {
          y_indent -= (rpos[1]-_1)/v_scale;
        }
        z_indent = rpos[2];
        if(z_indent<_0) { /* leave room for fonts of finite depth */
          z_indent+= _1;
          if(z_indent>_0) z_indent = _0;
        } else if(z_indent>_0) {
          z_indent-= _1;
          if(z_indent<_0) z_indent = _0;
        }
      }
      if(!pushed) {
        float *v = TextGetPos(G);
        float loc[3];
        float zero[3]= {0.0F,0.0F,0.0F};
        if(rpos) {
          SceneGetEyeNormal(G,v,loc);
          scale3f(loc,z_indent,loc);
          add3f(v,loc,loc);
          v = loc;
        }
        ScenePushRasterMatrix(G,v);
        TextSetPos(G,zero);
      } 
      if(rpos) {
        TextIndent(G,x_indent,y_indent);
      }
      while((c=*(st++))) {
        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--));
        }
        if(!unicnt) {
          CharFngrprnt fprnt;
          unsigned char *rgba;
          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;
          fprnt.u.i.flat = flat;
          {
            int id = CharacterFind(G,&fprnt);
            if(!id) {
              id = TypeFaceCharacterNew(I->TypeFace,&fprnt,size*sampling);
            }
            if(id) {
              if(kern_flag) {
                TextAdvance(G, TypeFaceGetKerning(I->TypeFace, 
                                                  last_c,
                                                  c,
                                                  size)/sampling);
              }
              CharacterRenderOpenGL(G,info,id); /* handles advance */
            }
          }
          kern_flag = true;
          last_c = c;
        }
      }
      if(!pushed) {
        ScenePopRasterMatrix(G);
      }
    }
  }
  return st;
}

static char *FontTypeRenderOpenGL(RenderInfo *info, CFontType *I,char *st,float size,float *rpos)
{
  return _FontTypeRenderOpenGL(info,I,st,size,false,rpos);
}
static char *FontTypeRenderOpenGLFlat(RenderInfo *info, CFontType *I,char *st,float size,float *rpos)
{
  return _FontTypeRenderOpenGL(info,I,st,size,true,rpos);
}

static char *FontTypeRenderRay(CRay *ray, CFontType *I,char *st,float size, float *rpos)
{
  register PyMOLGlobals *G = I->Font.G;
  unsigned int c;
  int kern_flag = false;
  unsigned int last_c = 0;
  int sampling = ray->Sampling;
  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 xn[3], yn[3], x_adj[3], y_adj[3], pos[3], *v;
  int unicode = 0;
  int unicnt = 0;

  if(st&&(*st)) {
    float origin[3],v_scale;
    SceneOriginGet(G,origin);
    v_scale = SceneGetScreenVertexScale(G,origin);

    if(rpos) {
      float loc[3];
      z_indent = rpos[2];
      if(z_indent<_0) { /* leave room for fonts of finite depth */
        z_indent+= _1;
        if(z_indent>_0) z_indent = _0;
      } else if(z_indent>_0) {
        z_indent-= _1;
        if(z_indent<_0) z_indent = _0;
      }

      v = TextGetPos(I->G);
      SceneGetEyeNormal(G,v,loc);
      scale3f(loc,z_indent,loc);
      add3f(v,loc,loc);
      TextSetPos(I->G,loc);
    }

    RayGetScaledAxes(ray,xn,yn);
    
    if(size<_0) {

      size = (int)(0.5F - size / v_scale);
    }

    if(rpos) {

      if(rpos[0]<_1) { /* we need to measure the string width before starting to draw */
        float factor = rpos[0]/2.0F - 0.5F;
        char *sst = st;
        if(factor<_m1) factor = -_1;
        if(factor>_0) factor = _0;
        while((c=*(sst++))) {
          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--));
          }
          if(!unicnt) {
            CharFngrprnt fprnt;
            unsigned char *rgba;
            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);
              if(!id) {
                id = TypeFaceCharacterNew(I->TypeFace,&fprnt,size*sampling);
              }
              if(id) {
                if(kern_flag) {
                  x_indent -= factor * TypeFaceGetKerning(I->TypeFace, 
                                                          last_c,
                                                          c,
                                                          size*sampling)/sampling;
                }
                x_indent -= factor * CharacterGetAdvance(G,1,id);
                kern_flag = true;
                last_c = c;
              }
            }
          }
        }
      }
      if(rpos[0]<_m1) {
        x_indent -= 2*(rpos[0]+_1)/v_scale;
      } else if(rpos[0]>_1) {
        x_indent -= 2*(rpos[0]-_1)/v_scale;
      }
      if(rpos[1]<_1) {
        float factor = -rpos[1]/2.0F + 0.5F;
        if(factor>_1) factor = _1;
        if(factor<_0) factor = _0;
        y_indent = 0.75F*sampling*size*factor;
      }
      if(rpos[1]<_m1) {
        y_indent -= 2*(rpos[1]+_1)/v_scale;
      } else if(rpos[1]>_1) {
        y_indent -= 2*(rpos[1]-_1)/v_scale;
      }
      v = TextGetPos(I->G);
      scale3f(xn, x_indent, x_adj);
      scale3f(yn, y_indent, y_adj);
      subtract3f(v,x_adj,pos);
      subtract3f(pos,y_adj,pos);
      TextSetPos(I->G,pos);
    }
    kern_flag = false;

    while((c=*(st++))) {
      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--));
      }
      if(!unicnt) {
        CharFngrprnt fprnt;
        unsigned char *rgba;
        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);
          if(!id) {
            id = TypeFaceCharacterNew(I->TypeFace,&fprnt,size*sampling);
          }
          if(id) {
            if(kern_flag) {
              float kern = TypeFaceGetKerning(I->TypeFace, 
                                              last_c,
                                              c,
                                              size*sampling)/sampling;
              v = TextGetPos(I->G);
              scale3f(xn, kern, x_adj);
              add3f(v,x_adj,pos);
              TextSetPos(I->G,pos);
            }
            ray->fCharacter(ray,id); /* handles advance */
            
            kern_flag = true;
            last_c = c;
          }
        }
      }
    }
  }
  return st;
}

static void FontTypeFree(CFont* font)
{
  register CFontType *I = (CFontType*)font;
  TypeFaceFree(I->TypeFace);
  OOFreeP(I);
}

CFont* FontTypeNew(PyMOLGlobals *G,unsigned char *dat,unsigned int len)
{  
  OOAlloc(G,CFontType);
  FontInit(G,&I->Font);
  I->G = G;
  I->Font.fRenderOpenGL = (FontRenderOpenGLFn*)FontTypeRenderOpenGL;
  I->Font.fRenderOpenGLFlat = (FontRenderOpenGLFn*)FontTypeRenderOpenGLFlat;
  I->Font.fRenderRay = (FontRenderRayFn*)FontTypeRenderRay;
  I->Font.fFree = FontTypeFree;
  I->TypeFace = TypeFaceLoad(G,dat,len);
  if(!I->TypeFace) {
    OOFreeP(I);
  }
  return (CFont*)I;
}



Generated by  Doxygen 1.6.0   Back to index