Logo Search packages:      
Sourcecode: pymol version File versions

FontGLUT.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_gl.h"
#include "Base.h"
#include "OOMac.h"
#include "FontGLUT.h"
#include "Text.h"
#include "Ray.h"
#include "Character.h"
#include "Scene.h"
#include "Util.h"
#include "Matrix.h"

static void FontGLUTSave(CFontGLUT *I)
{
  glGetIntegerv(GL_UNPACK_SWAP_BYTES,(GLint*)&I->swapbytes);
  glGetIntegerv(GL_UNPACK_LSB_FIRST, (GLint*)&I->lsbfirst);
  glGetIntegerv(GL_UNPACK_ROW_LENGTH, (GLint*)&I->rowlength);
  glGetIntegerv(GL_UNPACK_SKIP_ROWS, (GLint*)&I->skiprows);
  glGetIntegerv(GL_UNPACK_SKIP_PIXELS, (GLint*)&I->skippixels);
  glGetIntegerv(GL_UNPACK_ALIGNMENT, (GLint*)&I->alignment);
  
  glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
  glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}

static void FontGLUTRestore(CFontGLUT *I)
{
  glPixelStorei(GL_UNPACK_SWAP_BYTES, I->swapbytes);
  glPixelStorei(GL_UNPACK_LSB_FIRST, I->lsbfirst);
  glPixelStorei(GL_UNPACK_ROW_LENGTH, I->rowlength);
  glPixelStorei(GL_UNPACK_SKIP_ROWS, I->skiprows);
  glPixelStorei(GL_UNPACK_SKIP_PIXELS, I->skippixels);
  glPixelStorei(GL_UNPACK_ALIGNMENT, I->alignment);
}

static char *FontGLUTRenderOpenGL(RenderInfo *info,CFontGLUT *I,char *st,float size, float *rpos)
{
  register PyMOLGlobals *G = I->Font.G;
  if(G->ValidContext) {
    int c;
    FontGLUTBitmapFontRec *font_info = I->glutFont;
    int first,last;
    FontGLUTBitmapCharRec const *ch;
    int textured = SettingGetGlobal_b(G,cSetting_texture_fonts);
    int pushed = OrthoGetPushed(G);
    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;

    if(info)
      sampling = info->sampling;
    
    if(sampling>1) 
      textured = true;

    if(st&&(*st)) {

      float origin[3], v_scale;
      SceneOriginGet(G,origin);
      v_scale = SceneGetScreenVertexScale(G,origin);
      
      first = font_info->first;
      last = first + font_info->num_chars;
 
      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 = _m1;
          if(factor>_0) factor = _0;
          while((c=*(sst++))) {
            if ((c >= first) && (c < last)) {
              ch = font_info->ch[c - first];
              if (ch) {
                x_indent -= factor * ch->advance;
              }
            }
          }
        }
        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(textured && !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);
      } else if(!textured) {
        if(rpos) {
          float *v = TextGetPos(G);
          float loc[3];
          SceneGetEyeNormal(G,v,loc);
          scale3f(loc,z_indent,loc);
          add3f(v,loc,loc);
          TextSetPos(G,loc);
        }
      }

      if(rpos) {
        if(textured) {
          TextIndent(G,x_indent,y_indent);
        } else {
          float *v = TextGetPos(G);
          float indent[3];
          float loc[3];
          float *matrix = SceneGetMatrix(G);
          indent[0] = -v_scale * x_indent;
          indent[1] = -v_scale * y_indent;
          indent[2] = _0;
          MatrixInvTransformC44fAs33f3f(matrix,indent,indent);
          add3f(indent,v,loc);
          TextSetPos(G,loc);
        }
      }
      
      if(!textured) {
        glColor3fv(TextGetColor(G));
        glRasterPos4fv(TextGetPos(G));
        FontGLUTSave(I);
      }

      while((c=*(st++))) {
        if ((c >= first) && (c < last))
          {
            ch = font_info->ch[c - first];
            if (ch) {
              if(!textured) {
                
                glBitmap(ch->width, ch->height, 
                         ch->xorig, ch->yorig,
                         ch->advance, 0, ch->bitmap);
                TextAdvance(G,ch->advance);
              } else {
                CharFngrprnt fprnt;
                unsigned char *rgba;
                UtilZeroMem(&fprnt,sizeof(fprnt));
                fprnt.u.i.text_id = I->Font.TextID;
                fprnt.u.i.size = sampling;
                rgba = fprnt.u.i.color;
                TextGetColorUChar(G,rgba,rgba+1,rgba+2,rgba+3);
                fprnt.u.i.ch = (unsigned int)c;
                {
                  int id = CharacterFind(G,&fprnt);
                  if(!id) {
                    id = CharacterNewFromBitmap(G,ch->width, 
                                                ch->height, 
                                                (unsigned char*)ch->bitmap,
                                                (float)ch->xorig,
                                                (float)ch->yorig,
                                                (float)ch->advance,
                                                &fprnt,sampling);
                  }
                  if(id) {
                    CharacterRenderOpenGL(G,info,id); /* handles advance */
                  }
                }
              }
            }
          }
      }
                
      if(textured && !pushed) {
        ScenePopRasterMatrix(G);
      }
      if(!textured) {
        FontGLUTRestore(I); 
        glFlush(); /* workaround for screen flashes on late-model nVidia hardware */
      }
    }
  }
  return st;
}

static char *FontGLUTRenderRay(CRay *ray, CFontGLUT *I,char *st,float size, float *rpos)
{
  PyMOLGlobals *G = I->Font.G;
  int c;
  FontGLUTBitmapFontRec *font_info = I->glutFont;
  int first,last;
  FontGLUTBitmapCharRec const *ch;
  CharFngrprnt fprnt;
  unsigned char *rgba;
  int sampling = 1;
  float xn[3], yn[3], x_adj[3], y_adj[3], pos[3], *v;
  const float _0 = 0.0F, _1 = 1.0F, _m1 = -1.0F;
  float x_indent=0.0F, y_indent = 0.0F, z_indent = 0.0F;
  sampling = ray->Sampling;
  
  if(st&&(*st)) {
    float origin[3],v_scale;
    SceneOriginGet(G,origin);
    v_scale = SceneGetScreenVertexScale(G,origin);

    if(rpos) {
      float loc[3];
      v = TextGetPos(G);
      SceneGetEyeNormal(G,v,loc);
      scale3f(loc,rpos[2],loc);
      add3f(v,loc,loc);
      TextSetPos(G,loc);
    }

    RayGetScaledAxes(ray,xn,yn);

    UtilZeroMem(&fprnt,sizeof(fprnt));
    first = font_info->first;
    last = first + font_info->num_chars;
    fprnt.u.i.text_id = I->Font.TextID;           
    fprnt.u.i.size = sampling;
    rgba = fprnt.u.i.color;
    TextGetColorUChar(G,rgba,rgba+1,rgba+2,rgba+3);

    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++))) {
          fprnt.u.i.ch = (unsigned int) c;
          ch = font_info->ch[c - first];
          if (ch) {
            x_indent -= 2*factor * ch->advance;
          }
        }
      }
      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;
      }
      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(G);
      scale3f(xn, x_indent, x_adj);
      scale3f(yn, y_indent, y_adj);
      subtract3f(v,x_adj,pos);
      subtract3f(pos,y_adj,pos);
      TextSetPos(G,pos);
    }

    while((c=*(st++))) {
      if ((c >= first) && (c < last))
        {
          ch = font_info->ch[c - first];
          if (ch) {
            fprnt.u.i.ch = (unsigned int)c;
            {
              int id = CharacterFind(G,&fprnt);
              if(!id) {
                id = CharacterNewFromBitmap(G,ch->width, 
                                            ch->height, 
                                            (unsigned char*)ch->bitmap,
                                            (float)ch->xorig,
                                            (float)ch->yorig,
                                            (float)ch->advance,
                                            &fprnt,sampling);
              }
              if(id) ray->fCharacter(ray,id); /* handles advance */
            }
          }
        }
    }
  }
  return st;
}

void FontGLUTFree(CFont *I)
{
  OOFreeP(I);
}

CFont* FontGLUTNew(PyMOLGlobals *G,int font_code)
{  
  OOAlloc(G,CFontGLUT);
  FontInit(G,&I->Font);
  I->Font.fRenderOpenGL = (FontRenderOpenGLFn*)FontGLUTRenderOpenGL;
  I->Font.fRenderOpenGLFlat = (FontRenderOpenGLFn*)FontGLUTRenderOpenGL;
  I->Font.fRenderRay = (FontRenderRayFn*)FontGLUTRenderRay;
  I->Font.fFree = FontGLUTFree;
  switch(font_code) {
  case cFontGLUT9x15:
    I->glutFont = &FontGLUTBitmap9By15;
    break;
  case cFontGLUTHel10:
    I->glutFont = &FontGLUTBitmapHelvetica10;
    break;
  case cFontGLUTHel12:
    I->glutFont = &FontGLUTBitmapHelvetica12;
    break;
  case cFontGLUTHel18:
    I->glutFont = &FontGLUTBitmapHelvetica18;
    break;
  case cFontGLUT8x13:
  default:
    I->glutFont = &FontGLUTBitmap8By13;
    break;
  }
  return (CFont*)I;
}



Generated by  Doxygen 1.6.0   Back to index