/*********************************************************************** FONCTION : ---------- File OpenGl_tXfm.c : REMARQUES: ---------- Dans la methode alloc_new_font() des que l'on depasse (last_font > CACHE_SIZE) les performances s'ecroulent. HISTORIQUE DES MODIFICATIONS : -------------------------------- xx-xx-xx : xxx ; Creation. 26-06-96 : FMN ; Correction des textes clippes. On utilise glXUseXFont() 27-06-96 : FMN ; Correction hauteur des textes. 14-02-97 : FMN ; Suppression de MYGLXUSEXFONT 12-09-97 : CAL ; Protection si tXfmfindfont echoue. modifs dans tXfmfindfont, tXfmsetfont et tXfmprstr 02-11-98 : FMN ; PRO12916: Desactivation de la gestion du CharacterExpansionFactor qui n'est pas implementee. Ce point sera traite de maniere complete avec l'utilisation d'une librairie specifique de type GLC. Pour le moment il est preferable de le desactiver car ce parametre n'est pas vraiment necessaire. 30-11-98 : FMN ; S4069 : Textes toujours visibles 02.15.100 JR : Clutters ************************************************************************/ #define xTRACE 1 #define BUC60821 /*GG 12/02/01 allow tu use the nearest font size*/ #define IMP281101 /*GG Enable to display chars with accent*/ #define OCC2934 /*SAN Texture-mapped fonts on WNT */ #define OCC7667 /* asl Export to vector graphic file */ #ifdef OCC7667 #define GL2PS_TEXT 16 #endif /*----------------------------------------------------------------------*/ /* UNIX XWINDOW */ /*----------------------------------------------------------------------*/ #ifndef WNT /*----------------------------------------------------------------------*/ /* * Includes */ #include #include #include #include #include #include #include #include #include #include #ifdef OCC2934 # include #endif #ifdef OCC7667 void exportText( char* str, char* fontname, GLfloat height, GLfloat x, GLfloat y, GLfloat z, GLboolean is2d ); #endif #include #include #include /*----------------------------------------------------------------------*/ /* * Constantes */ #ifdef DECOSF1 #define MAX_X11_COORD ((1 << 12) - 1) /* JWR - limit coord range for ZLXp-L1 */ #else #define MAX_X11_COORD (1 << 15) #endif #define MAX_GLYPHS_PER_GRAB 512 /* this is big enough for 2^9 glyph character sets */ /*----------------------------------------------------------------------*/ /* * Prototypes fonctions internes */ static int getXfontind(float *, float , int ); static void getXsizefromstr(float *, char **, int ); static txfmfonthandle alloc_new_font(char *); /*----------------------------------------------------------------------*/ /* * Prototypes variables statiques */ txfmfonthandle current_fonthandle = NULL; static char current_fontname[255]; static txfmfonthandle tXfmfontset[CACHE_SIZE]; static int last_font = 0; static FontEntry fontEntry[] = { {"Courier", "-adobe-courier-medium-r-normal--*-*-*-*-*-*-iso8859-1", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0}, {"Times-Roman", "-adobe-times-medium-r-normal--*-*-*-*-*-*-iso8859-1", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0}, {"Times-Bold", "-adobe-times-bold-r-normal--*-*-*-*-*-*-iso8859-1", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0}, {"Times-Italic", "-adobe-times-medium-i-normal--*-*-*-*-*-*-iso8859-1", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0}, {"Times-BoldItalic", "-adobe-times-bold-i-normal--*-*-*-*-*-*-iso8859-1", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0}, {"ZapfChancery-MediumItalic", "-adobe-itc zapf chancery-medium-i-normal--*-*-*-*-*-*-iso8859-1", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0}, {"Symbol", "-adobe-symbol-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0}, {"ZapfDingbats", "-adobe-itc zapf dingbats-medium-r-normal--*-*-*-*-*-*-adobe-fontspecific", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0}, {"Rock", "-sgi-rock-medium-r-normal--*-*-*-*-p-*-iso8859-1", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0}, {"Iris", "--iris-medium-r-normal--*-*-*-*-m-*-iso8859-1", { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, 0} }; /*----------------------------------------------------------------------*/ /* * Fonctions publiques externes */ /*------------------------------------------------------------------------*/ void sizeString(char *str, GLint *Width, GLint *Ascent, GLint *Descent) { int dir = 0, asc = 0, des = 0; XCharStruct mes; if (current_fonthandle != NULL && current_fonthandle->fontInfo != NULL && str != NULL ) { XTextExtents(current_fonthandle->fontInfo, str, strlen(str), &dir, &asc, &des, &mes); #ifdef TRACE printf("XTextExtents::asc = %d des = %d width = %d \n", asc, des, mes.width); #endif *Ascent = current_fonthandle->fontInfo->ascent; *Descent = current_fonthandle->fontInfo->descent; *Width = mes.width; } else { *Ascent = 0; *Descent = 0; *Width = 0; } } /*----------------------------------------------------------------------*/ txfmfonthandle tXfmfindfont(Display *fdpy, char *fontname, float bestfont_size) { txfmfonthandle fonthandle; char **fontList; int i, a, count, xfont_ind; int found_font = 0, found_entry = 0; float req_size; current_fonthandle = (txfmfonthandle) 0; #ifdef BUC60821 req_size = bestfont_size/call_tox_getpitchsize()*1.36F; /* 98/72 dpi*/ #else req_size = bestfont_size*1.36F; /* 98/72 dpi*/ #endif /* * Verifie que la (fonte,taille) n'ont pas deja ete traite */ for (i=0, a=0; i < last_font && !found_font; i++) { if(strcmp(tXfmfontset[i]->fontname, fontname) == 0) { if((tXfmfontset[i]->charsize) == req_size) { fonthandle = tXfmfontset[i]; found_font = 1; current_fonthandle = fonthandle; current_fonthandle->charsize = req_size; current_fonthandle->dpy = fdpy; /*strcpy(fonthandle->Xfontname, fontname);*/ strcpy(current_fontname, fontname); break; } } } if (found_font) return (current_fonthandle); /* * Recherche dans les fontes disponibles: fontEntry */ for (i=0 ; i< NUM_FONT_ENTRIES ; i++) { if( strcmp(fontname, fontEntry[i].name) == 0 ) { found_entry = 1; break; } } if (!found_entry) return((txfmfonthandle) 0); /* Pour optimiser il faudrait un putXsizetostring */ fontList = XListFonts(fdpy, fontEntry[i].xlfd, NUM_FONT_SIZES, &count); if (!count) { /* if the font is not found in Unix library the default font is used */ i = 0; fontList = XListFonts(fdpy, fontEntry[i].xlfd, NUM_FONT_SIZES, &count); } if (!count) return((txfmfonthandle) 0); getXsizefromstr(fontEntry[i].xsizes, fontList, count); fontEntry[i].count = count; xfont_ind = getXfontind(fontEntry[i].xsizes, req_size, count); #ifdef TRACE printf("Size %f Selected %s\n", bestfont_size, fontList[xfont_ind]); #endif found_font = 0; for (i=0, a=0; i < last_font && !found_font; i++) { if(strcmp(tXfmfontset[i]->Xfontname, fontList[xfont_ind]) == 0) { fonthandle = tXfmfontset[i]; found_font = 1; current_fonthandle = fonthandle; current_fonthandle->charsize = req_size; current_fonthandle->dpy = fdpy; strcpy(current_fontname, fontname); break; } } if (found_font) return (current_fonthandle); fonthandle = alloc_new_font(fontname); fonthandle->charsize = req_size; strcpy(current_fontname, fontList[xfont_ind]); strcpy(fonthandle->Xfontname, fontList[xfont_ind]); fonthandle->dpy = fdpy; current_fonthandle = fonthandle; XFreeFontNames(fontList); return(current_fonthandle); } /*----------------------------------------------------------------------*/ GLuint tXfmsetfont( float txfmxscale, float txfmyscale) { GLuint pBase = 0; Font id; unsigned int first, last; /* int i;*/ txfmfonthandle fonthandle; XFontStruct *fontInfo = 0; int isNeedUpdate; if (current_fonthandle ==(txfmfonthandle) 0) return (0); fonthandle = current_fonthandle; isNeedUpdate = 0; /* = 1 if doesn't exist font or if needs for regenerate font ( Number of LastFont is exeeds maxFontSize, i.e.fonthandle->dirty = 1 ) */ if ( fonthandle->listBase ) { if ( !fonthandle->dirty ) { isNeedUpdate = 0; pBase = fonthandle->listBase; /*OCC6247*/ /*return(fonthandle->listBase);*/ /*OCC6247*/ } else /* dirty , reutilise fonthandle */ { isNeedUpdate = 1; pBase = fonthandle->listBase; } } else { isNeedUpdate = 1; /* Nouvelle fonte */ pBase = glGenLists(NUM_CHAR_FONT); } if( isNeedUpdate ) { fontInfo = XLoadQueryFont(fonthandle->dpy, current_fontname); } if (fontInfo == NULL) { if(fonthandle->fontInfo == NULL) return GL_FALSE; fontInfo=fonthandle->fontInfo; } id = fontInfo->fid; first = (int)fontInfo->min_char_or_byte2; last = (int)fontInfo->max_char_or_byte2; if( isNeedUpdate ) { glXUseXFont(id, first, last-first+1, pBase+first); } fonthandle->listBase = pBase; fonthandle->dirty = 0; fonthandle->fontInfo = fontInfo; fonthandle->xscale = txfmxscale; fonthandle->yscale = txfmyscale; /* XFreeFont( fonthandle->dpy, fontInfo); */ return(pBase); } /*----------------------------------------------------------------------*/ void tXfmprstr(unsigned char *str, GLuint Base, GLfloat x, GLfloat y, GLfloat z ) { /* OCC7456 abd 14.12.2004 Text alignment attributes */ GLdouble projMatrix[4][4], modelMatrix[4][4]; GLint viewport[4]; GLint widthFont, ascentFont, descentFont, heightFont; GLdouble xw, yw, zw; GLdouble xv, yv, zv; GLdouble xdis = 0., ydis = 0.; GLint renderMode; /* SAMTECH modif -- Geoff Levner 19/7/2007 */ TEL_ALIGN_DATA align; CMN_KEY key; /* OCC7456 abd 14.12.2004 Text alignment attributes */ if (Base == 0) return; /* OCC7456 abd 14.12.2004 Text alignment attributes */ key.id = TelTextAlign; key.data.pdata = &align; TsmGetAttri( 1, &key ); sizeString( (char*) str, &widthFont, &ascentFont, &descentFont ); switch( align.Hmode ) { case CALL_PHIGS_HOR_NORM: case CALL_PHIGS_HOR_LEFT: xdis = 0.; break; case CALL_PHIGS_HOR_RIGHT: xdis = (GLdouble)widthFont; break; case CALL_PHIGS_HOR_CTR: xdis = (GLdouble)widthFont / 2.; break; default: xdis = 0.; } switch( align.Vmode ) { case CALL_PHIGS_VERT_NORM: case CALL_PHIGS_VERT_BASE: ydis = 0.; break; case CALL_PHIGS_VERT_TOP: ydis = (GLdouble)ascentFont; break; case CALL_PHIGS_VERT_CAP: ydis = (GLdouble)(ascentFont); break; case CALL_PHIGS_VERT_HALF: ydis = (GLdouble)(ascentFont - descentFont)/2; break; case CALL_PHIGS_VERT_BOTTOM: ydis = -(GLdouble)descentFont; break; default: ydis = 0.; } /*OCC7456 abd 14.12.2004 Text alignment attributes */ /*OCC7456 abd 14.12.2004 Text alignment attributes */ glGetDoublev( GL_MODELVIEW_MATRIX, (GLdouble*)modelMatrix ); glGetDoublev( GL_PROJECTION_MATRIX, (GLdouble*)projMatrix ); glGetIntegerv( GL_VIEWPORT, (GLint*)viewport ); gluProject( x, y, z, (GLdouble*)modelMatrix, (GLdouble*)projMatrix, (GLint*)viewport, &xw, &yw, &zw ); gluUnProject( xw - xdis, yw - ydis, zw, (GLdouble*)modelMatrix, (GLdouble*)projMatrix, (GLint*)viewport, &xv, &yv, &zv ); glRasterPos3d(xv, yv, zv); /*OCC7456 abd 14.12.2004 Text alignment attributes */ #ifdef OCC7667 /* SAMTECH modif -- Geoff Levner 19/7/2007 -- added render mode test */ glGetIntegerv(GL_RENDER_MODE, &renderMode); if (renderMode == GL_FEEDBACK) { exportText( (char*) str, current_fontname, current_fonthandle->charsize * call_tox_getpitchsize(), x, y, z, GL_FALSE ); glRasterPos3f( x, y, z ); } #endif glPushAttrib(GL_LIST_BIT); glListBase(Base); glCallLists(strlen((char *) str), GL_UNSIGNED_BYTE, (GLubyte *)str); glPopAttrib(); } /*----------------------------------------------------------------------*/ /* * Fonctions statiques */ static void getXsizefromstr(float *xfontsize, char **Liste, int count) { int i, j, point; int numdash = 0; char temp[3]; for (i=0 ; i= xfontsize[i]) { /* Ne pas retourner une fonte > */ cur_diff = abs(best_size - xfontsize[i]); if (cur_diff < prev_diff ) { prev_diff=cur_diff; font_ind=i; } } } return(font_ind); } /*----------------------------------------------------------------------*/ static txfmfonthandle alloc_new_font( char * name) { txfmfonthandle handle; if (last_font > CACHE_SIZE) { handle = tXfmfontset[(rand())%CACHE_SIZE]; handle->dirty = 1; } else { handle = (txfmfonthandle) malloc(sizeof (TXFM_FONTHANDLE)); tXfmfontset[last_font] = handle; last_font++; strcpy(handle->fontname, name); handle->listBase = 0; handle->dirty = 0; handle->fontInfo = NULL; } return(handle); } /*----------------------------------------------------------------------*/ /* Windows NT */ /*----------------------------------------------------------------------*/ #else /*----------------------------------------------------------------------*/ /* * Includes */ # include # include /*#include #include #include */ #ifdef OCC2934 # include #endif # include # include # define NUM_FONT_ENTRIES (sizeof(fontEntry)/sizeof(FONT_ENTRY)) # define MAX_FONT_SIZES 8 # define MAX_FONT_SCALES 16 #ifdef OCC2934 #define MAX_FONT_TEXTURES 16 #define MAX_NB_CHARS 256 #define CHAR_SIZE 16 #endif typedef struct _font_handle { GLuint listBase; HGLRC curRC; float xScale; float yScale; UINT useCount; } FONT_HANDLE; typedef struct _font_struct { LONG lWidth; LONG lHeight; LONG lInternalLeading; LONG lDescent; GLsizei listRange; float charSize; UINT useCount; FONT_HANDLE fh[ MAX_FONT_SCALES ]; } FONT_STRUCT; #ifdef OCC2934 typedef struct _tm_font_handle { GLint textureId; GLint texSize; HGLRC curRC; float scale; float charRatios[MAX_NB_CHARS]; } TM_FONT_HANDLE; #endif typedef struct _font_entry { char* name; TCHAR lfFaceName[ LF_FACESIZE ]; FONT_STRUCT fs[ MAX_FONT_SIZES ]; #ifdef OCC2934 TM_FONT_HANDLE tfh[ MAX_FONT_TEXTURES ]; #endif } FONT_ENTRY; #ifdef OCC7667 void exportText( char* str, char* fontname, GLfloat height, GLfloat x, GLfloat y, GLfloat z, GLboolean is2d ); #endif /*----------------------------------------------------------------------*/ /* * Variables statiques */ static FONT_ENTRY fontEntry[] = { { "Courier" , "Courier New" }, { "Times-Roman" , "Times New Roman" }, { "Times-Bold" , "Times New Roman Bold" }, { "Times-Italic" , "Times New Roman Italic" }, { "Times-BoldItalic" , "Times New Roman Bold Italic" }, { "ZapfChancery-MediumItalic", "Script" }, { "Symbol" , "Symbol" }, { "ZapfDingbats" , "WingDings" }, { "Rock" , "Arial" }, { "Iris" , "Lucida Console" } }; /* end fontEntry */ static int curFont = -1; static int curSize = -1; static int curScale = -1; #ifdef OCC2934 static int useTexFont = 0; static int curTexFont = -1; TEL_POINT char_offsets[4] = { { 0., 0., 0. }, { 0., 0., 0. }, { 0., 0., 0. }, { 0., 0., 0. } }; #endif /*----------------------------------------------------------------------*/ /* * Prototypes */ static void loadNewFont ( FONT_HANDLE*, float, BOOL ); static void updateSizeUsage ( void ); static void updateScaleUsage ( void ); /*----------------------------------------------------------------------*/ void sizeString(char *str, GLint *Width, GLint *Ascent, GLint *Descent) { /* int dir, asc, des;*/ if (curFont != -1) { *Ascent = (int)fontEntry[ curFont ].fs[ curSize ].lHeight - (int)fontEntry[ curFont ].fs[ curSize ].lInternalLeading - (int)fontEntry[ curFont ].fs[ curSize ].lDescent; *Descent = (int)fontEntry[ curFont ].fs[ curSize ].lDescent; *Width = fontEntry[ curFont ].fs[ curSize ].lWidth * strlen(str); } else { *Ascent = 0; *Descent = 0; *Width = 0; } #ifdef TRACE printf("sizeString::asc = %d des = %d width = %d \n", *Ascent, *Descent, *Width); #endif } #ifdef OCC2934 /* loadTexFont(): Prepares a square texture containing glyphs for the given font */ /* Current limitations: - texture of fixed size 256 x 256 pixels is used, - each glyph occupies a 16 x 16 square in the texture, - fixed font height (16) is used for texture creation */ static GLint loadTexFont(char* fontName, TM_FONT_HANDLE* fontHandle) { GLint tex_id = -1; HFONT font; HDC hMemDC, hDC = NULL; char str[2] = " "; int i, j, l, num, code; BITMAPINFO bi; HBITMAP hBmp, hOldBmp; const int spacing = 2; /* spacing between characters in a string */ GLubyte fontBits [256 * 256 * 3]; /* font bitmap array: RGB */ GLubyte ifontBits[256 * 256 * 2]; /* texture array: luminance and alpha */ int charWidths[MAX_NB_CHARS]; if ( !fontHandle ) return tex_id; memset(fontHandle, 0, sizeof(TM_FONT_HANDLE)); fontHandle->curRC = wglGetCurrentContext(); fontHandle->texSize = 256; fontHandle->scale = 1.f; /* draw the font glyphs on the square bitmap */ font = CreateFont(-16, /* Height Of Font*/ 0, /* Width Of Font*/ 0, /* Angle Of Escapement*/ 0, /* Orientation Angle*/ FW_BOLD, /* Font Weight*/ FALSE, /* Italic*/ FALSE, /* Underline*/ FALSE, /* Strikeout*/ ANSI_CHARSET, /* Character Set Identifier*/ OUT_TT_PRECIS, /* Output Precision*/ CLIP_DEFAULT_PRECIS, /* Clipping Precision*/ NONANTIALIASED_QUALITY, /* Output Quality*/ FF_MODERN|DEFAULT_PITCH, /* Family And Pitch*/ fontName); /* Font Name*/ hDC = wglGetCurrentDC(); hMemDC = CreateCompatibleDC(hDC); hBmp = CreateCompatibleBitmap(hDC, fontHandle->texSize, fontHandle->texSize); hOldBmp = (HBITMAP)SelectObject(hMemDC, hBmp); SelectObject(hMemDC, font); SetTextColor(hMemDC, RGB(255, 255, 255)); SetBkColor (hMemDC, RGB(0, 0, 0)); GetCharWidth32( hDC, 0, MAX_NB_CHARS - 1, charWidths ); for (i = 0; i < 16; i++) for (j = 0; j < 16; j++) { code = i * 16 + j; str[0] = (char)code; l = strlen(str); TextOut(hMemDC, j * CHAR_SIZE, i * CHAR_SIZE, str, l ); /* calculate advance ratio for each character */ fontHandle->charRatios[code] = (float)( charWidths[code] + spacing ) / (float)CHAR_SIZE; } /* retrieve the font bitmap */ memset(&bi, 0, sizeof(BITMAPINFOHEADER)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biHeight = -fontHandle->texSize; bi.bmiHeader.biWidth = fontHandle->texSize; bi.bmiHeader.biCompression = BI_RGB; SelectObject(hMemDC, hOldBmp); num = GetDIBits(hMemDC, hBmp, 0, fontHandle->texSize, fontBits, &bi, DIB_RGB_COLORS); /* prepare an array of alpha and luminance values */ for ( i = 0; i < fontHandle->texSize; i++ ) for( j = 0; j < fontHandle->texSize; j++ ) { ifontBits[( i * fontHandle->texSize + j ) * 2] = fontBits[( i * fontHandle->texSize + j ) * 3]; ifontBits[( i * fontHandle->texSize + j ) * 2 + 1] = fontBits[( i * fontHandle->texSize + j ) * 3]; } /* create the font texture */ glGenTextures(1, &tex_id); glBindTexture(GL_TEXTURE_2D, tex_id); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, fontHandle->texSize, fontHandle->texSize, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, ifontBits); fontHandle->textureId = tex_id; return tex_id; } /* texPrint(): displays a string using texture , is used to convert quickly 16-pixel offset in viewport co-ordinates to offsets in world co-ordinates */ /* Current limitations: - texture of fixed size 256 x 256 pixels is used */ static void texPrint( Tchar* data, TM_FONT_HANDLE* fontHandle, TEL_POINT* offsets ) { int i, l, code; float a, b, c, d, tx0, tx1, ty0, ty1; float x, y, z, divisor; if ( !data || !fontHandle ) return; /* starting point for the text (offsets[0] is used instead of (0; 0; 0) in order to move the text slightly towards the eye) */ x = offsets[0].xyz[0]; y = offsets[0].xyz[1]; z = offsets[0].xyz[2]; divisor = (float)(fontHandle->texSize - 1); /*BUG OCC11904 - remember parameters of texture mapping*/ glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT ); glEnable(GL_TEXTURE_2D); glAlphaFunc(GL_GEQUAL, 0.5f); glEnable(GL_ALPHA_TEST); glBindTexture(GL_TEXTURE_2D, fontHandle->textureId); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); l = strlen(data); glBegin(GL_QUADS); for (i = 0; i < l; i++) { code = data[i]; /* compute texture coordinates */ a = (float)((code % CHAR_SIZE) * CHAR_SIZE); b = (float)((code % CHAR_SIZE) * CHAR_SIZE + CHAR_SIZE - 1); c = (float)((code >> 4) * CHAR_SIZE + CHAR_SIZE - 1); d = (float)((code >> 4) * CHAR_SIZE); tx0 = a / divisor; tx1 = b / divisor; ty0 = c / divisor; ty1 = d / divisor; glTexCoord2f(tx0, ty0); glVertex3f(x, y, z); glTexCoord2f(tx1, ty0); glVertex3f(x+offsets[1].xyz[0], y+offsets[1].xyz[1], z+offsets[1].xyz[2]); glTexCoord2f(tx1, ty1); glVertex3f(x+offsets[2].xyz[0], y+offsets[2].xyz[1], z+offsets[2].xyz[2]); glTexCoord2f(tx0, ty1); glVertex3f(x+offsets[3].xyz[0], y+offsets[3].xyz[1], z+offsets[3].xyz[2]); /* using glTranslate here is less efficient */ x += offsets[1].xyz[0] * fontHandle->charRatios[code]; y += offsets[1].xyz[1] * fontHandle->charRatios[code]; z += offsets[1].xyz[2] * fontHandle->charRatios[code]; } glEnd(); /* OCC11904 - Restoring old texture mapping attributes to avoid conflicts with OpenGl_TextureBox.c functionslity */ glPopAttrib(); } void WNTUseTexMappedFont( int flag ) { int i; if (flag && !useTexFont && curFont != -1) { FONT_ENTRY* fe = &fontEntry[curFont]; HGLRC curRC = wglGetCurrentContext(); for (i = 0; i < MAX_FONT_TEXTURES; i++ ) { if (fe->tfh[i].curRC == curRC) break; } if (i == MAX_FONT_TEXTURES) { i = 0; glDeleteTextures(1, &(fe->tfh[i].textureId)); } if ( fe->tfh[i].curRC != curRC || fe->tfh[i].textureId == 0) loadTexFont( fe->lfFaceName, &(fe->tfh[i]) ); curTexFont = i; } useTexFont = flag; } #endif /* OCC2934 */ /*----------------------------------------------------------------------*/ void WNTFindFont ( char* fontName, float bestSize ) { int i, min_idx; UINT min_val; FONT_STRUCT* fs; #ifdef OCC2934 int texLoadNeeded = 0; #endif for ( i = 0; i < NUM_FONT_ENTRIES; ++i ) if ( lstrcmp ( fontEntry[ i ].name, fontName ) == 0 ) break; if ( i == NUM_FONT_ENTRIES ) curFont = curSize = -1; else { #ifdef OCC2934 texLoadNeeded = (useTexFont && curFont != i); #endif fs = &( fontEntry[ i ].fs[ 0 ] ); curFont = i; for ( i = 0; i < MAX_FONT_SIZES; ++i ) { if ( fs[ i ].charSize == 0 ) { curSize = i; loadNewFont ( &( fs[ i ].fh[ 0 ] ), bestSize, TRUE ); break; } else if ( fs[ i ].charSize == bestSize ) { curSize = i; updateSizeUsage (); break; } /* end if */ } /* end for */ if ( i == MAX_FONT_SIZES ) { min_val = UINT_MAX; min_idx = 0; for ( i = 0; i < MAX_FONT_SIZES; ++i ) if ( fs[ i ].useCount < min_val ) { min_val = fs -> useCount; min_idx = i; } /* end if */ curSize = min_idx; loadNewFont ( &( fs[ min_idx ].fh[ 0 ] ), bestSize, TRUE ); } /* end if */ } /* end else */ #ifdef OCC2934 if (texLoadNeeded) { FONT_ENTRY* fe = &fontEntry[curFont]; HGLRC curRC = wglGetCurrentContext(); for (i = 0; i < MAX_FONT_TEXTURES; i++ ) { if (fe->tfh[i].curRC == curRC) break; } if (i == MAX_FONT_TEXTURES) { i = 0; glDeleteTextures(1, &(fe->tfh[i].textureId)); } if ( fe->tfh[i].curRC != curRC || fe->tfh[i].textureId == 0) loadTexFont( fe->lfFaceName, &(fe->tfh[i]) ); curTexFont = i; } #endif } /* end WNTFindFont */ /*----------------------------------------------------------------------*/ GLuint WNTSetFont ( float xScale, float yScale ) { int i, min_idx; UINT min_val; GLuint retVal = 0; BOOL newScale = FALSE; FONT_HANDLE* fh; HGLRC hGLRC; if ( curFont != -1 && curSize != -1 ) { hGLRC = wglGetCurrentContext (); fh = &( fontEntry[ curFont ].fs[ curSize ].fh[ 0 ] ); for ( i = 0; i < MAX_FONT_SCALES; ++i ) if ( fh[ i ].xScale == xScale && fh[ i ].yScale == yScale && fh[ i ].curRC == hGLRC ) { retVal = fh[ i ].listBase; curScale = i; updateScaleUsage (); break; } else if ( fh[ i ].xScale == 0.0F && fh[ i ].yScale == 0.0F ) { newScale = TRUE; break; } /* end if */ if ( !retVal ) { if ( newScale ) { fh[ i ].xScale = xScale; fh[ i ].yScale = yScale; curScale = i; loadNewFont ( &fh[ i ], 0.0F, FALSE ); retVal = fh[ i ].listBase; } else { min_val = UINT_MAX; min_idx = 0; for ( i = 0; i < MAX_FONT_SCALES; ++i ) if ( fh[ i ].useCount < min_val ) { min_val = fh -> useCount; min_idx = i; } /* end if */ fh[ min_idx ].xScale = xScale; fh[ min_idx ].yScale = yScale; curScale = i; loadNewFont ( &fh[ min_idx ], 0.0F, FALSE ); retVal = fh[ min_idx ].listBase; } /* end else ( newScale . . . ) */ } /* end if ( !retVal . . . ) */ } /* end if ( curFont != -1 . . . ) */ return retVal; } /* end WNTSetFont */ /*----------------------------------------------------------------------*/ #ifdef OCC2934 void WNTPuts ( char* str, GLuint base, int is2d, GLfloat x, GLfloat y, GLfloat z ) { #else void WNTPuts ( char* str, GLuint base ) { #endif GLfloat quant[ 4 ]; GLfloat array[ 4 ]; /*OCC7456 abd 14.12.2004 Text alingnment attributes */ GLdouble projMatrix[4][4], modelMatrix[4][4]; GLint viewport[4]; GLint widthFont, ascentFont, descentFont, heightFont, leadingFont; GLdouble xw, yw, zw; GLdouble xv, yv, zv; GLdouble xdis = 0., ydis = 0.; GLint renderMode; /* SAMTECH modif -- Geoff Levner 19/7/2007 */ TEL_ALIGN_DATA aling; CMN_KEY key; key.id = TelTextAlign; key.data.pdata = &aling; TsmGetAttri( 1, &key ); sizeString( str, &widthFont, &ascentFont, &descentFont ); heightFont = fontEntry[ curFont ].fs[ curSize ].lHeight; leadingFont = fontEntry[ curFont ].fs[ curSize ].lInternalLeading; switch( aling.Hmode ) { case CALL_PHIGS_HOR_NORM: case CALL_PHIGS_HOR_LEFT: xdis = 0.; break; case CALL_PHIGS_HOR_RIGHT: xdis = (GLdouble)widthFont; break; case CALL_PHIGS_HOR_CTR: xdis = (GLdouble)widthFont / 2.; break; default: xdis = 0.; } switch( aling.Vmode ) { case CALL_PHIGS_VERT_NORM: case CALL_PHIGS_VERT_BASE: ydis = 0.; break; case CALL_PHIGS_VERT_TOP: ydis = (GLdouble)ascentFont; break; case CALL_PHIGS_VERT_CAP: ydis = (GLdouble)(ascentFont - leadingFont) - 1; break; case CALL_PHIGS_VERT_HALF: ydis = (GLdouble)(ascentFont - descentFont)/2; break; case CALL_PHIGS_VERT_BOTTOM: ydis = -(GLdouble)descentFont; break; default: ydis = 0.; } /*OCC7456 abd 14.12.2004 Text alingnment attributes */ #ifdef OCC7667 /* SAMTECH modif -- Geoff Levner 19/7/2007 -- added render mode test */ glGetIntegerv(GL_RENDER_MODE, &renderMode); if (renderMode == GL_FEEDBACK) { exportText( str, fontEntry[curFont].name, ( GLfloat )fontEntry[ curFont ].fs[ curSize ].lHeight, x, y, z, is2d!=0 ); } #endif #ifdef OCC2934 if ( !is2d && useTexFont && curTexFont >= 0 ) { /* Set up the text position */ glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(x, y, z); texPrint( str, &(fontEntry[curFont].tfh[curTexFont]), char_offsets ); /* Restore previous matrices */ glMatrixMode(GL_TEXTURE); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); return; } if (is2d) glRasterPos2f(x, y); else { /*OCC7456 abd 14.12.2004 Text alingnment attributes */ glGetDoublev( GL_MODELVIEW_MATRIX, (GLdouble*)modelMatrix ); glGetDoublev( GL_PROJECTION_MATRIX, (GLdouble*)projMatrix ); glGetIntegerv( GL_VIEWPORT, (GLint*)viewport ); gluProject( x, y, z, (GLdouble*)modelMatrix, (GLdouble*)projMatrix, (GLint*)viewport, &xw, &yw, &zw ); gluUnProject( xw - xdis, yw - ydis, zw, (GLdouble*)modelMatrix, (GLdouble*)projMatrix, (GLint*)viewport, &xv, &yv, &zv ); glRasterPos3d(xv, yv, zv); /*OCC7456 abd 14.12.2004 Text alingnment attributes */ //glRasterPos3f(x, y, z); } #endif glAlphaFunc ( GL_EQUAL, 1.0F ); glEnable ( GL_ALPHA_TEST ); glListBase ( base ); glGetFloatv ( GL_CURRENT_COLOR, quant ); array[ 0 ] = 0.0F; array[ 1 ] = quant[ 0 ]; glPixelMapfv ( GL_PIXEL_MAP_I_TO_R, 2, array ); array[ 0 ] = 0.0F; array[ 1 ] = quant[ 1 ]; glPixelMapfv ( GL_PIXEL_MAP_I_TO_G, 2, array ); array[ 0 ] = 0.0F; array[ 1 ] = quant[ 2 ]; glPixelMapfv ( GL_PIXEL_MAP_I_TO_B, 2, array ); array[ 0 ] = 0.0F; array[ 1 ] = 1.0F; glPixelMapfv ( GL_PIXEL_MAP_I_TO_A, 2, array ); glPixelTransferi ( GL_MAP_COLOR, GL_TRUE ); glCallLists ( lstrlen ( str ), GL_UNSIGNED_BYTE, str ); /*san -- 12/11/2004 -- OCC7190 Texture-mapped fonts don't work, as soon as any old-style (bitmap) text is displayed */ glPixelTransferi(GL_MAP_COLOR, GL_FALSE); glDisable ( GL_ALPHA_TEST ); } /* end WNTPuts */ /*----------------------------------------------------------------------*/ static void loadNewFont ( FONT_HANDLE* fh, float size, BOOL newSize ) { int i; HDC hDC; HFONT hFont, hOldFont; FONT_HANDLE* fhTemp; LOGFONT lf; TEXTMETRIC tm; hDC = wglGetCurrentDC (); ZeroMemory ( ( PVOID )&lf, sizeof ( LOGFONT ) ); if ( newSize ) { fhTemp = fontEntry[ curFont ].fs[ curSize ].fh; for ( i = 0; i < MAX_FONT_SCALES; ++i ) if ( fhTemp[ i ].listBase ) { glDeleteLists (fhTemp[ i ].listBase, fontEntry[ curFont ].fs[ curSize ].listRange); ZeroMemory ( ( PVOID )&fhTemp[ i ], sizeof ( FONT_HANDLE ) ); } else break; fh -> xScale = 1.0F; fh -> yScale = 1.0F; fontEntry[ curFont ].fs[ curSize ].charSize = size; lf.lfHeight = ( LONG )size; lf.lfCharSet = ANSI_CHARSET; lf.lfQuality = PROOF_QUALITY; lstrcpy ( lf.lfFaceName, fontEntry[ curFont ].lfFaceName ); hFont = CreateFontIndirect ( &lf ); hOldFont = SelectObject ( hDC, hFont ); GetTextMetrics ( hDC, &tm ); fh -> curRC = wglGetCurrentContext (); #ifdef IMP281101 fontEntry[ curFont ].fs[ curSize ].listRange = tm.tmLastChar + 1; #else fontEntry[ curFont ].fs[ curSize ].listRange = tm.tmLastChar - tm.tmFirstChar + 1; #endif fh -> listBase = glGenLists (fontEntry[ curFont ].fs[ curSize ].listRange); if (!wglUseFontBitmaps (hDC, 0, fontEntry[ curFont ].fs[ curSize ].listRange, fh -> listBase)) printf ("OpenGL interface: wglUseFontBitmaps failed. Error code %d\n",GetLastError ()); SelectObject ( hDC, hOldFont ); DeleteObject ( hFont ); fontEntry[ curFont ].fs[ curSize ].lWidth = tm.tmAveCharWidth; fontEntry[ curFont ].fs[ curSize ].lHeight = tm.tmHeight; fontEntry[ curFont ].fs[ curSize ].lInternalLeading = tm.tmInternalLeading; fontEntry[ curFont ].fs[ curSize ].lDescent = tm.tmDescent; } else { /* new scale */ if ( fh -> listBase ) glDeleteLists (fh -> listBase, fontEntry[ curFont ].fs[ curSize ].listRange); lf.lfHeight = ( LONG )( fontEntry[ curFont ].fs[ curSize ].lHeight * fh -> yScale ); lf.lfWidth = ( LONG )( fontEntry[ curFont ].fs[ curSize ].lWidth * fh -> xScale ); lf.lfCharSet = ANSI_CHARSET; lf.lfQuality = PROOF_QUALITY; lstrcpy ( lf.lfFaceName, fontEntry[ curFont ].lfFaceName ); hFont = CreateFontIndirect ( &lf ); hOldFont = SelectObject ( hDC, hFont ); fh -> listBase = glGenLists (fontEntry[ curFont ].fs[ curSize ].listRange); if (!wglUseFontBitmaps (hDC, 0, fontEntry[ curFont ].fs[ curSize ].listRange, fh -> listBase)) printf ("OpenGL interface: wglUseFontBitmaps failed. Error code %d\n",GetLastError ()); SelectObject ( hDC, hOldFont ); DeleteObject ( hFont ); fh -> curRC = wglGetCurrentContext (); } /* end else ( newSize . . . ) */ } /* end loadNewFont */ /*----------------------------------------------------------------------*/ static void updateSizeUsage ( void ) { int i; if ( fontEntry[ curFont ].fs[ curSize ].useCount == UINT_MAX ) for ( i = 0; i < MAX_FONT_SIZES; ++i ) fontEntry[ curFont ].fs[ i ].useCount >>= 1; ++fontEntry[ curFont ].fs[ curSize ].useCount; } /* end updateSizeUsage */ /*----------------------------------------------------------------------*/ static void updateScaleUsage ( void ) { int i; if ( fontEntry[ curFont ].fs[ curSize ].fh[ curScale ].useCount == UINT_MAX ) for ( i = 0; i < MAX_FONT_SCALES; ++i ) fontEntry[ curFont ].fs[ curSize ].fh[ i ].useCount >>= 1; ++fontEntry[ curFont ].fs[ curSize ].fh[ curScale ].useCount; } /* end updateScaleUsage */ #endif /* WNT */ /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ #ifdef OCC7667 void exportString( char* str ) { int i, n; if( str ) { glPassThrough( ( GLfloat )strlen( str ) ); for( i=0, n=strlen( str ); i