glbitmapfont.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:28k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: glbitmapfont.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 20:50:25  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: glbitmapfont.cpp,v 1000.3 2004/06/01 20:50:25 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Mike DiCuccio
  35.  *
  36.  * File Description:
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <gui/opengl/glbitmapfont.hpp>
  41. #include <gui/opengl/gldlist.hpp>
  42. #include "glutbitmap.h"
  43. #include <math.h>
  44. #include <stdio.h>
  45. #include <util/static_map.hpp>
  46. extern "C" {
  47.     // clean fonts
  48.     extern BitmapFontRec ncbi_clean_6;
  49.     extern BitmapFontRec ncbi_clean_8;
  50.     extern BitmapFontRec ncbi_clean_10;
  51.     extern BitmapFontRec ncbi_clean_12;
  52.     extern BitmapFontRec ncbi_clean_13;
  53.     extern BitmapFontRec ncbi_clean_14;
  54.     extern BitmapFontRec ncbi_clean_15;
  55.     extern BitmapFontRec ncbi_clean_16;
  56.     // courier fonts
  57.     extern BitmapFontRec ncbi_courier_6;
  58.     extern BitmapFontRec ncbi_courier_8;
  59.     extern BitmapFontRec ncbi_courier_10;
  60.     extern BitmapFontRec ncbi_courier_12;
  61.     extern BitmapFontRec ncbi_courier_14;
  62.     extern BitmapFontRec ncbi_courier_18;
  63.     extern BitmapFontRec ncbi_courier_20;
  64.     extern BitmapFontRec ncbi_courier_24;
  65.     // fixed size fonts
  66.     extern BitmapFontRec ncbi_fixed_6;
  67.     extern BitmapFontRec ncbi_fixed_8;
  68.     extern BitmapFontRec ncbi_fixed_10;
  69.     extern BitmapFontRec ncbi_fixed_12;
  70.     extern BitmapFontRec ncbi_fixed_14;
  71.     extern BitmapFontRec ncbi_fixed_18;
  72.     extern BitmapFontRec ncbi_fixed_20;
  73.     extern BitmapFontRec ncbi_fixed_20;
  74.     // helvetica fonts
  75.     extern BitmapFontRec ncbi_helvetica_6;
  76.     extern BitmapFontRec ncbi_helvetica_8;
  77.     extern BitmapFontRec ncbi_helvetica_10;
  78.     extern BitmapFontRec ncbi_helvetica_12;
  79.     extern BitmapFontRec ncbi_helvetica_14;
  80.     extern BitmapFontRec ncbi_helvetica_18;
  81.     extern BitmapFontRec ncbi_helvetica_20;
  82.     extern BitmapFontRec ncbi_helvetica_24;
  83.     // ludica fonts
  84.     extern BitmapFontRec ncbi_lucida_6;
  85.     extern BitmapFontRec ncbi_lucida_8;
  86.     extern BitmapFontRec ncbi_lucida_10;
  87.     extern BitmapFontRec ncbi_lucida_12;
  88.     extern BitmapFontRec ncbi_lucida_14;
  89.     extern BitmapFontRec ncbi_lucida_18;
  90.     extern BitmapFontRec ncbi_lucida_20;
  91.     extern BitmapFontRec ncbi_lucida_24;
  92.     // times fonts
  93.     extern BitmapFontRec ncbi_times_6;
  94.     extern BitmapFontRec ncbi_times_8;
  95.     extern BitmapFontRec ncbi_times_10;
  96.     extern BitmapFontRec ncbi_times_12;
  97.     extern BitmapFontRec ncbi_times_14;
  98.     extern BitmapFontRec ncbi_times_18;
  99.     extern BitmapFontRec ncbi_times_20;
  100.     extern BitmapFontRec ncbi_times_24;
  101. }
  102. BEGIN_NCBI_SCOPE
  103. typedef pair<CGlBitmapFont::EFont, BitmapFontPtr> TFontPair;
  104. static const TFontPair sc_Fonts[] = {
  105.     TFontPair(CGlBitmapFont::eBitmap5x7,   &ncbi_fixed_8),
  106.     TFontPair(CGlBitmapFont::eBitmap8x13,  &ncbi_fixed_12),
  107.     TFontPair(CGlBitmapFont::eBitmap9x15,  &ncbi_fixed_14),
  108.     TFontPair(CGlBitmapFont::eBitmap10x20, &ncbi_fixed_18),
  109.     TFontPair(CGlBitmapFont::eBitmap12x24, &ncbi_fixed_20),
  110.     TFontPair(CGlBitmapFont::eHelvetica6,  &ncbi_helvetica_6),
  111.     TFontPair(CGlBitmapFont::eHelvetica8,  &ncbi_helvetica_8),
  112.     TFontPair(CGlBitmapFont::eHelvetica10, &ncbi_helvetica_10),
  113.     TFontPair(CGlBitmapFont::eHelvetica12, &ncbi_helvetica_12),
  114.     TFontPair(CGlBitmapFont::eHelvetica14, &ncbi_helvetica_14),
  115.     TFontPair(CGlBitmapFont::eHelvetica18, &ncbi_helvetica_18),
  116.     TFontPair(CGlBitmapFont::eHelvetica20, &ncbi_helvetica_20),
  117.     TFontPair(CGlBitmapFont::eHelvetica24, &ncbi_helvetica_24),
  118.     TFontPair(CGlBitmapFont::eLucida6,  &ncbi_lucida_6),
  119.     TFontPair(CGlBitmapFont::eLucida8,  &ncbi_lucida_8),
  120.     TFontPair(CGlBitmapFont::eLucida10, &ncbi_lucida_10),
  121.     TFontPair(CGlBitmapFont::eLucida12, &ncbi_lucida_12),
  122.     TFontPair(CGlBitmapFont::eLucida14, &ncbi_lucida_14),
  123.     TFontPair(CGlBitmapFont::eLucida18, &ncbi_lucida_18),
  124.     TFontPair(CGlBitmapFont::eLucida20, &ncbi_lucida_20),
  125.     TFontPair(CGlBitmapFont::eLucida24, &ncbi_lucida_24),
  126.     TFontPair(CGlBitmapFont::eCourier6,  &ncbi_courier_6),
  127.     TFontPair(CGlBitmapFont::eCourier8,  &ncbi_courier_8),
  128.     TFontPair(CGlBitmapFont::eCourier10, &ncbi_courier_10),
  129.     TFontPair(CGlBitmapFont::eCourier12, &ncbi_courier_12),
  130.     TFontPair(CGlBitmapFont::eCourier14, &ncbi_courier_14),
  131.     TFontPair(CGlBitmapFont::eCourier18, &ncbi_courier_18),
  132.     TFontPair(CGlBitmapFont::eCourier20, &ncbi_courier_20),
  133.     TFontPair(CGlBitmapFont::eCourier24, &ncbi_courier_24),
  134.     TFontPair(CGlBitmapFont::eClean6,  &ncbi_clean_6),
  135.     TFontPair(CGlBitmapFont::eClean8,  &ncbi_clean_8),
  136.     TFontPair(CGlBitmapFont::eClean10, &ncbi_clean_10),
  137.     TFontPair(CGlBitmapFont::eClean12, &ncbi_clean_12),
  138.     TFontPair(CGlBitmapFont::eClean14, &ncbi_clean_13),
  139.     TFontPair(CGlBitmapFont::eClean18, &ncbi_clean_14),
  140.     TFontPair(CGlBitmapFont::eClean20, &ncbi_clean_15),
  141.     TFontPair(CGlBitmapFont::eClean24, &ncbi_clean_16),
  142.     TFontPair(CGlBitmapFont::eFixed8,  &ncbi_fixed_8),
  143.     TFontPair(CGlBitmapFont::eFixed10, &ncbi_fixed_10),
  144.     TFontPair(CGlBitmapFont::eFixed12, &ncbi_fixed_12),
  145.     TFontPair(CGlBitmapFont::eFixed14, &ncbi_fixed_14),
  146.     TFontPair(CGlBitmapFont::eFixed18, &ncbi_fixed_18),
  147.     TFontPair(CGlBitmapFont::eFixed20, &ncbi_fixed_20),
  148.     TFontPair(CGlBitmapFont::eTimesRoman6,  &ncbi_times_6),
  149.     TFontPair(CGlBitmapFont::eTimesRoman8,  &ncbi_times_8),
  150.     TFontPair(CGlBitmapFont::eTimesRoman10, &ncbi_times_10),
  151.     TFontPair(CGlBitmapFont::eTimesRoman12, &ncbi_times_12),
  152.     TFontPair(CGlBitmapFont::eTimesRoman14, &ncbi_times_14),
  153.     TFontPair(CGlBitmapFont::eTimesRoman18, &ncbi_times_18),
  154.     TFontPair(CGlBitmapFont::eTimesRoman20, &ncbi_times_20),
  155.     TFontPair(CGlBitmapFont::eTimesRoman24, &ncbi_times_24)
  156. };
  157. typedef CStaticArrayMap<CGlBitmapFont::EFont, BitmapFontPtr> TFontMap;
  158. static const TFontMap sc_FontMap(sc_Fonts, sizeof (sc_Fonts));
  159. static inline
  160. const BitmapFontPtr s_GetFont(CGlBitmapFont::EFont font)
  161. {
  162.     TFontMap::const_iterator iter = sc_FontMap.lower_bound(font);
  163.     if (iter->first == font) {
  164.         // exact match
  165.         return iter->second;
  166.     } else if (iter->first != font) {
  167.         // probably off by size
  168.         CGlBitmapFont::EFontFace face =
  169.             static_cast<CGlBitmapFont::EFontFace>
  170.             (font & 0xff);
  171.         CGlBitmapFont::EFontFace this_face =
  172.             static_cast<CGlBitmapFont::EFontFace>
  173.             (iter->first & 0xff);
  174.         if (this_face == face) {
  175.             // faces match, return font
  176.             return iter->second;
  177.         } else {
  178.             // faces don't match
  179.             // we need to jump forward or back to get the right face
  180.             TFontMap::const_iterator back    = iter;
  181.             TFontMap::const_iterator forward = iter;
  182.             for ( ;
  183.                   back != sc_FontMap.begin()  &&
  184.                   forward != sc_FontMap.end();  ) {
  185.                 if (back != sc_FontMap.begin()) {
  186.                     CGlBitmapFont::EFontFace this_face =
  187.                         static_cast<CGlBitmapFont::EFontFace>
  188.                         (back->first & 0xff);
  189.                     if (this_face == face) {
  190.                         return back->second;
  191.                     }
  192.                     --back;
  193.                 }
  194.                 if (forward != sc_FontMap.end()) {
  195.                     CGlBitmapFont::EFontFace this_face =
  196.                         static_cast<CGlBitmapFont::EFontFace>
  197.                         (forward->first & 0xff);
  198.                     if (this_face == face) {
  199.                         return forward->second;
  200.                     }
  201.                     ++forward;
  202.                 }
  203.             }
  204.         }
  205.     }
  206.     NCBI_THROW(CException, eUnknown, "gl font not found");
  207. }
  208. //
  209. // return the width of a single character
  210. // this is really the *advance* of a character
  211. //
  212. static float s_GetCharAdvance(char c, const BitmapFontRec* font_ptr)
  213. {
  214.     if (c  <   font_ptr->first ||
  215.         c  >=  font_ptr->first + font_ptr->num_chars) {
  216.         return 0.0f;
  217.     }
  218.     const BitmapCharRec *ch = font_ptr->ch[c - font_ptr->first];
  219.     if ( !ch ) {
  220.         return 0.0f;
  221.     }
  222.     return ch->advance;
  223. }
  224. static float s_GetCharWidth(char c, const BitmapFontRec* font_ptr)
  225. {
  226.     if (c  <   font_ptr->first ||
  227.         c  >=  font_ptr->first + font_ptr->num_chars) {
  228.         return 0.0f;
  229.     }
  230.     const BitmapCharRec *ch = font_ptr->ch[c - font_ptr->first];
  231.     if ( !ch ) {
  232.         return 0.0f;
  233.     }
  234.     return (float)ch->width;
  235. }
  236. CGlBitmapFont::CGlBitmapFont()
  237.     : m_Font(eBitmap8x13)
  238. {
  239.     SetFont(eBitmap8x13);
  240. }
  241. CGlBitmapFont::CGlBitmapFont(EFont font)
  242.     : m_Font(font)
  243. {
  244.     SetFont(font);
  245. }
  246. CGlBitmapFont::~CGlBitmapFont()
  247. {
  248. }
  249. void CGlBitmapFont::SetFontFace(EFontFace face)
  250. {
  251.     EFont font = static_cast<EFont>((m_Font & 0xff) | face);
  252.     SetFont(font);
  253. }
  254. void CGlBitmapFont::SetFontSize(EFontSize size)
  255. {
  256.     EFont font = static_cast<EFont>((m_Font & ~0xff) | size);
  257.     SetFont(font);
  258. }
  259. void CGlBitmapFont::SetFont(EFont font)
  260. {
  261.     if (font != m_Font) {
  262.         m_Font = font;
  263.         // we must also invalidate all of our display lists
  264.         // this may be expensive, as it forces regeneration of display
  265.         // lists the next time we render any characters
  266.         for (int i = 0;  i < 256;  ++i) {
  267.             if (m_Chars[i]) {
  268.                 m_Chars[i]->Invalidate();
  269.             }
  270.         }
  271.     }
  272. }
  273. template<class TOutputMethod>
  274. void DoTextOut(TOutputMethod& method)
  275. {
  276.     // save a bunch of states
  277.     GLint swapbytes;
  278.     GLint lsbfirst;
  279.     GLint rowlength;
  280.     GLint skiprows;
  281.     GLint skippixels;
  282.     GLint alignment;
  283.     glGetIntegerv(GL_UNPACK_SWAP_BYTES,  &swapbytes);
  284.     glGetIntegerv(GL_UNPACK_LSB_FIRST,   &lsbfirst);
  285.     glGetIntegerv(GL_UNPACK_ROW_LENGTH,  &rowlength);
  286.     glGetIntegerv(GL_UNPACK_SKIP_ROWS,   &skiprows);
  287.     glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
  288.     glGetIntegerv(GL_UNPACK_ALIGNMENT,   &alignment);
  289.     glPixelStorei(GL_UNPACK_SWAP_BYTES,  GL_FALSE);
  290.     glPixelStorei(GL_UNPACK_LSB_FIRST,   GL_FALSE);
  291.     glPixelStorei(GL_UNPACK_ROW_LENGTH,  0);
  292.     glPixelStorei(GL_UNPACK_SKIP_ROWS,   0);
  293.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  294.     glPixelStorei(GL_UNPACK_ALIGNMENT,   1);
  295.     // render our text
  296.     method();
  297.     // restore states
  298.     glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
  299.     glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
  300.     glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
  301.     glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
  302.     glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
  303.     glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
  304. }
  305. class CTextPrinter
  306. {
  307. public:
  308.     CTextPrinter(const char* text, const BitmapFontPtr& font_ptr)
  309.         : m_Text(text),
  310.           m_FontPtr(font_ptr)
  311.     {
  312.     }
  313.     void operator()()
  314.     {        
  315.         for (const char* p = m_Text;  p  &&  *p;  ++p) {
  316.             if (*p <  m_FontPtr->first  ||
  317.                 *p >= m_FontPtr->first + m_FontPtr->num_chars) {
  318.                 continue;
  319.             }
  320.             const BitmapCharRec *ch = m_FontPtr->ch[*p - m_FontPtr->first];
  321.             if (ch ) {
  322.                 glBitmap(ch->width, ch->height, ch->xorig, ch->yorig,
  323.                          ch->advance, 0, ch->bitmap);
  324.             }
  325.         }
  326.     };
  327. protected:
  328.     const char* m_Text;
  329.     const BitmapFontPtr& m_FontPtr;
  330. };
  331. //
  332. // TextOut()
  333. // This version performs most of the low-level work.  It simply
  334. // outputs text at a previously determined raster position
  335. //
  336. void CGlBitmapFont::TextOut(const char* text) const
  337. {
  338.     GLint mode;
  339.     glGetIntegerv(GL_RENDER_MODE, &mode);
  340.     switch (mode) {
  341.     case GL_FEEDBACK:
  342.         {{
  343.             GLfloat pos[4];
  344.             GLfloat col[4];
  345.             glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
  346.             glGetFloatv(GL_CURRENT_RASTER_COLOR, col);
  347.             const CGlColor c(col, 4);
  348.             typedef vector<float> TFList;
  349.             TFList vectext =
  350.                 CGlFeedbackFont::EncodeText(pos, c, text, strlen(text));
  351.             ITERATE (TFList, it, vectext) {
  352.                 glPassThrough(*it);
  353.             }
  354.         }}
  355.         break;
  356.     default:
  357.         {{
  358.             // first, retrieve our OpenGL font
  359.             const BitmapFontPtr font_ptr = s_GetFont(m_Font);
  360.             CTextPrinter    printer(text, font_ptr);
  361.             DoTextOut(printer);
  362.         }}
  363.         break;
  364.     }
  365. }
  366. class CTextArrayPrinter
  367. {
  368. public:
  369.     CTextArrayPrinter(const char* text,
  370.                       float x, float y, float dx, float dy,
  371.                       float scale_x, float scale_y,
  372.                       const BitmapFontPtr& font_ptr)
  373.         : m_Text(text),
  374.           m_X(x),
  375.           m_Y(y),
  376.           m_dX(dx),
  377.           m_dY(dy),
  378.           m_ScaleX(scale_x),
  379.           m_ScaleY(scale_y),
  380.           m_FontPtr(font_ptr)
  381.     {
  382.     }
  383.     void operator()()
  384.     {        
  385.         float k_x = m_ScaleX / 2;
  386.         float k_y = m_ScaleY / 2;
  387.         for (const char* p = m_Text;  p  &&  *p;  ++p) {
  388.             if (*p  <   m_FontPtr->first ||
  389.                 *p  >=  m_FontPtr->first + m_FontPtr->num_chars) {
  390.                 continue;
  391.             }
  392.             const BitmapCharRec *ch = m_FontPtr->ch[*p - m_FontPtr->first];
  393.             if (ch ) {
  394.                 int ind = p - m_Text;
  395.                 float pos_x = m_X + ind * m_dX;
  396.                 float pos_y = m_Y + ind * m_dY;
  397.                 float off_x = ch->width * k_x; // to current coord system
  398.                 float off_y = ch->height * k_y; // to current coord system
  399.                 
  400.                 glRasterPos2f(pos_x - off_x, pos_y - off_y);
  401.                 glBitmap(ch->width, ch->height, ch->xorig, ch->yorig,
  402.                          0, 0, ch->bitmap);
  403.                 /**
  404.                 if ( !m_Chars[*p] ) {
  405.                     m_Chars[*p].Reset(new CGlDisplayList());
  406.                 }
  407.                 if (m_Chars[*p]->IsValid()) {
  408.                     m_Chars[*p]->Call();
  409.                 } else {
  410.                     CGlDisplayListCompile COMPILE(*m_Chars[*p],
  411.                                                   GL_COMPILE_AND_EXECUTE);
  412.                     glBitmap(ch->width, ch->height, ch->xorig, ch->yorig,
  413.                              ch->advance, 0, ch->bitmap);
  414.                 }
  415.                 **/
  416.             }
  417.         }
  418.     };
  419. protected:
  420.     const char* m_Text;
  421.     float   m_X, m_Y;
  422.     float   m_dX, m_dY;
  423.     float   m_ScaleX, m_ScaleY;
  424.     const BitmapFontPtr& m_FontPtr;
  425. };
  426. void    CGlBitmapFont::ArrayTextOut(float x, float y, float dx, float dy, const char* text,
  427.                                     float scale_x, float scale_y) const
  428. {    
  429.     GLint mode;
  430.     glGetIntegerv(GL_RENDER_MODE, &mode);
  431.     switch (mode) {
  432.     case GL_FEEDBACK:
  433.         {{
  434.             _ASSERT(false); // not implemented yet
  435.         }}
  436.         break;
  437.     default:
  438.         {{
  439.             // first, retrieve our OpenGL font
  440.             const BitmapFontPtr font_ptr = s_GetFont(m_Font);
  441.             CTextArrayPrinter    printer(text, x, y, dx, dy, scale_x, scale_y, font_ptr);
  442.             DoTextOut(printer);
  443.         }}
  444.         break;
  445.     }
  446. }
  447. //
  448. // TextOut()
  449. // This version performs some label alignment in the specified box
  450. //
  451. void CGlBitmapFont::TextOut(float x, float y, float w, float h,
  452.                             const char* text, int align,
  453.                             ETruncate trunc) const
  454. {
  455.     string str;
  456.     switch (trunc) {
  457.     case eTruncate_None:
  458.         str = text;
  459.         break;
  460.     case eTruncate_Empty:
  461.     case eTruncate_Ellipsis:
  462.         x_Truncate(text, w, trunc, &str);
  463.         break;
  464.     }
  465.     
  466.     float ras_x, ras_y;
  467.     // FL_ALIGN_RIGHT or FL_ALIGN_CENTER are applied to horz position only if
  468.     // FL_ALIGN_LEFT is not specifed
  469.     if(align & FL_ALIGN_LEFT)  { 
  470.         ras_x = x;
  471.     } else if (align & FL_ALIGN_RIGHT)  { // right justify            
  472.         float text_wid = TextWidth(str.c_str());
  473.         ras_x = x + (w - text_wid);
  474.     } else  { // center
  475.         float text_wid = TextWidth(str.c_str());
  476.         ras_x = x + (w - text_wid) * 0.5f;
  477.     }
  478.     if (align & FL_ALIGN_BOTTOM)  {
  479.         ras_y = y;
  480.     } else if (align & FL_ALIGN_TOP) { // skip down enough to keep our text inside            
  481.         float text_ht = TextHeight();
  482.         ras_y = y + h - text_ht;
  483.     } else { // if nothing given or FL_ALIGN_CENTER is specified - center vertically        
  484.         float text_ht = TextHeight();
  485.         ras_y = y + (h - text_ht) * 0.5f;
  486.     }
  487.     
  488.     TextOut(ras_x, ras_y, str.c_str());
  489. }
  490. void CGlBitmapFont::TextOut(float x, float y, const char* text) const
  491. {
  492.     glRasterPos2f(x, y);
  493.     TextOut(text);
  494. }
  495. //
  496. // compute the width of a string of characters
  497. // this will count out at most n characters, stopping on a null
  498. // note that the comparison function used for 'n' is 0 or non-zero -
  499. // so passing '-1' for 'n' means 'compute until a null character is found'
  500. // This allows us to avoid calling strlen()
  501. //
  502. float CGlBitmapFont::TextWidth(const char* text, int n) const
  503. {
  504.     return GetMetric(eMetric_TextWidth, text, n);
  505. }
  506. //
  507. // compute the length of a null-terminated string
  508. //
  509. float CGlBitmapFont::TextWidth(const char* text) const
  510. {
  511.     return GetMetric(eMetric_TextWidth, text);
  512. }
  513. //
  514. // compute the height of a string
  515. //
  516. float CGlBitmapFont::TextHeight(void) const
  517. {
  518.     return GetMetric(eMetric_CharHeight);
  519. }
  520. //
  521. // generic text metric retrieval
  522. //
  523. float CGlBitmapFont::GetMetric(EMetric metric,
  524.                                const char* text, int text_len) const
  525. {
  526.     // first, retrieve our OpenGL font
  527.     const BitmapFontRec* font_ptr = s_GetFont(m_Font);
  528.     switch (metric) {
  529.     case eMetric_CharHeight:
  530.         //
  531.         // return the height of a capital letter
  532.         //
  533.         {{
  534.             // we first scan the capital letters
  535.             // this gives us the height of the text without descents but with
  536.             // ascents
  537.             static const char* sc_caps = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  538.             GLsizei max_ht = 0;
  539.             for (const char* p = sc_caps;  p  &&  *p;  ++p) {
  540.                 const BitmapCharRec *ch = font_ptr->ch[*p - font_ptr->first];
  541.                 if ( !ch ) {
  542.                     continue;
  543.                 }
  544.                 GLsizei ht = GLsizei(ch->height - ch->yorig);
  545.                 max_ht     = max(max_ht, ht);
  546.             }
  547.             return (float)max_ht;
  548.         }}
  549.     case eMetric_FullCharHeight:
  550.         //
  551.         // return the maximal height of all available characters
  552.         //
  553.         {{
  554.             // we first scan the capital letters
  555.             // this gives us the height of the text without descents but with
  556.             // ascents
  557.             GLsizei max_ht = 0;
  558.             for (int i = font_ptr->first;  i < font_ptr->num_chars;  ++i) {
  559.                 const BitmapCharRec *ch = font_ptr->ch[i];
  560.                 if ( !ch ) {
  561.                     continue;
  562.                 }
  563.                 GLsizei ht = GLsizei(ch->height - ch->yorig);
  564.                 max_ht     = max(max_ht, ht);
  565.             }
  566.             return (float)max_ht;
  567.         }}
  568.     case eMetric_AvgCharWidth:
  569.         //
  570.         // return the maximal height of all available characters
  571.         //
  572.         {{
  573.             // we first scan the capital letters
  574.             // this gives us the height of the text without descents but with
  575.             // ascents
  576.             GLfloat wid   = 0;
  577.             GLsizei count = 0;
  578.             for (int i = font_ptr->first;  i < font_ptr->num_chars;  ++i) {
  579.                 const BitmapCharRec *ch = font_ptr->ch[i];
  580.                 if ( !ch ) {
  581.                     continue;
  582.                 }
  583.                 wid += ch->advance;
  584.                 ++count;
  585.             }
  586.             return wid / float(count);
  587.         }}
  588.     case eMetric_MaxCharWidth:
  589.         //
  590.         // return the maximal height of all available characters
  591.         //
  592.         {{
  593.             // we first scan the capital letters
  594.             // this gives us the height of the text without descents but with
  595.             // ascents
  596.             GLfloat wid   = 0;
  597.             GLsizei count = 0;
  598.             for (int i = font_ptr->first;  i < font_ptr->num_chars;  ++i) {
  599.                 const BitmapCharRec *ch = font_ptr->ch[i];
  600.                 if ( !ch ) {
  601.                     continue;
  602.                 }
  603.                 wid = max(ch->advance, wid);
  604.                 ++count;
  605.             }
  606.             return wid;
  607.         }}
  608.     case eMetric_TextWidth:
  609.     case eMetric_FullTextWidth:
  610.         //
  611.         // return the width of the text with or without the final advance
  612.         //
  613.         if (text) {
  614.             float sum = 0.0f;
  615.             // iterate over our text
  616.             const char* p = text;
  617.             for ( ;  text_len  &&  p  &&  *p;  ++p, --text_len) {
  618.                 sum += s_GetCharAdvance(*p, font_ptr);
  619.             }
  620.             // adjust for the trailing character
  621.             if (p  &&  metric == eMetric_TextWidth) {
  622.                 --p;
  623.                 sum -= s_GetCharAdvance(*p, font_ptr);
  624.                 sum += s_GetCharWidth(*p, font_ptr);
  625.             }
  626.             return sum;
  627.         }
  628.         break;
  629.     default:
  630.         break;
  631.     }
  632.     return 0.0f;
  633. }
  634. string CGlBitmapFont::Truncate(const char* text, float w, ETruncate trunc) const
  635. {
  636.     string res;
  637.     x_Truncate(text, w, trunc, &res);
  638.     return res;
  639. }
  640. string CGlBitmapFont::Truncate(const string& str, float w, ETruncate trunc) const
  641. {
  642.     string res;
  643.     x_Truncate(str.c_str(), w, trunc, &res);
  644.     return res;
  645. }
  646. // Truncate a string for display.  This version will return the maximum
  647. // number of characters that can fit into the given width
  648. int CGlBitmapFont::x_Truncate(const char* text, float w, ETruncate trunc,
  649.                               string* str) const
  650. {
  651.     // first, retrieve our OpenGL font
  652.     const BitmapFontRec* font_ptr = s_GetFont(m_Font);
  653.     static const char* sc_ellipsis = "...";
  654.     const char* ellip = NULL;
  655.     const char* end_pos = text;
  656.     switch (trunc) {
  657.     case eTruncate_None:
  658.         end_pos = text + strlen(text);
  659.         break;
  660.     case eTruncate_Ellipsis:
  661.         {{
  662.             // first, do a blunt cut
  663.             int pos = x_Truncate(text, w, eTruncate_Empty);
  664.             end_pos = text + pos;
  665.             if ( !*end_pos ) {
  666.                 // we can fit the whole thing
  667.                 break;
  668.             }
  669.             // adjust for the ellipsis
  670.             float e_wid = TextWidth(sc_ellipsis);
  671.             while (e_wid > 0) {
  672.                 ellip = sc_ellipsis;
  673.                 e_wid -= s_GetCharWidth(*end_pos, font_ptr);
  674.                 if (end_pos > text) {
  675.                     --end_pos;
  676.                 } else {
  677.                     break;
  678.                 }
  679.             }
  680.         }}
  681.         break;
  682.     case eTruncate_Empty:
  683.         for ( ;  end_pos  &&  *end_pos  && w >= 0;  ++end_pos) {
  684.             float wid = s_GetCharAdvance(*end_pos, font_ptr);
  685.             if (w - wid < 0) {
  686.                 wid = s_GetCharWidth(*end_pos, font_ptr);
  687.             }
  688.             w -= wid;
  689.         }
  690.         if (w < 0) {
  691.             --end_pos;
  692.         }
  693.         break;
  694.     }
  695.     if (end_pos < text) {
  696.         end_pos = text;
  697.     }
  698.     if (str) {
  699.         str->assign(text, end_pos);
  700.         if (ellip) {
  701.             *str += ellip;
  702.         }
  703.     }
  704.     return end_pos - text;
  705. }
  706. static const  char* kPostfixes[] = { "", " K", " M", " G" };
  707. string CTextUtils::FormatSeparatedNumber(int Number, bool b_postfix)
  708. {
  709.     bool bNegative = Number < 0;
  710.     Number = abs(Number);
  711.     string s_number, s_postfix;
  712.     char cSep = ',';
  713.     int i_postfix = 0;
  714.     if(Number != 0  &&  b_postfix)    {
  715.         int Rest = Number % 1000;        
  716.         for( i_postfix = 0; Rest == 0; i_postfix++)  {
  717.             Number = Number / 1000;        
  718.             Rest = Number % 1000;            
  719.         }
  720.         _ASSERT(i_postfix < 4);
  721.         s_postfix = kPostfixes[i_postfix];
  722.     }    
  723.     char sTemplGroup[] = " %.3d";
  724.     sTemplGroup[0] = cSep;
  725.     char sTemplLast[] = "%d";  
  726.     char S[20];    
  727.     do    {
  728.         int Rest = Number % 1000;
  729.         Number = Number / 1000;
  730.         sprintf(S, Number ? sTemplGroup : sTemplLast, Rest);            
  731.         s_number = string(S) + s_number;    
  732.     } while(Number);
  733.     s_number += s_postfix;
  734.     if(bNegative) {
  735.         s_number = "-" + s_number;
  736.     }
  737.     return s_number;
  738. }
  739. int CTextUtils::GetCharsCount(int Number)
  740. {
  741.     int MaxDigits = (int) ceil( log10((double) Number)); // decimal digist in number
  742.     int nSep = (MaxDigits - 1) / 3; // number of separators between groups
  743.     return MaxDigits + nSep;
  744. }
  745. END_NCBI_SCOPE
  746. /*
  747.  * ===========================================================================
  748.  * $Log: glbitmapfont.cpp,v $
  749.  * Revision 1000.3  2004/06/01 20:50:25  gouriano
  750.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  751.  *
  752.  * Revision 1.20  2004/05/21 22:27:44  gorelenk
  753.  * Added PCH ncbi_pch.hpp
  754.  *
  755.  * Revision 1.19  2004/05/21 12:44:12  dicuccio
  756.  * Clean-up of font handling.  Extended available font faces; added new font faces
  757.  * (clean, fixed)
  758.  *
  759.  * Revision 1.18  2004/05/03 13:03:15  dicuccio
  760.  * Fixed compiler warnings on MSVC7
  761.  *
  762.  * Revision 1.17  2004/03/12 15:29:19  dicuccio
  763.  * Use CStaticArrayMap<> to manage font lookups
  764.  *
  765.  * Revision 1.16  2004/03/11 17:37:21  dicuccio
  766.  * Split font face and font size from font specification
  767.  *
  768.  * Revision 1.15  2004/03/03 15:06:21  yazhuk
  769.  * Changed labels alignment algorithm
  770.  *
  771.  * Revision 1.14  2003/12/10 21:32:07  ucko
  772.  * +<stdio.h> for sprintf()
  773.  *
  774.  * Revision 1.13  2003/11/18 17:45:47  dicuccio
  775.  * Formatting changes
  776.  *
  777.  * Revision 1.12  2003/11/17 21:03:39  yazhuk
  778.  * Refactored Truncate() and TextOut() functions, added ArrayTextOut(),
  779.  * renamed GetDigitsCount() to GetCharsCount()
  780.  *
  781.  * Revision 1.11  2003/10/29 22:27:06  yazhuk
  782.  * Added CTextUtils class
  783.  *
  784.  * Revision 1.10  2003/10/09 17:58:39  lebedev
  785.  * Trancate method made public
  786.  *
  787.  * Revision 1.9  2003/10/07 19:38:53  dicuccio
  788.  * Temporarily disable display list inside of font - restores letters after window hide
  789.  *
  790.  * Revision 1.8  2003/09/29 15:34:45  dicuccio
  791.  * Reworked TextHeight() and TextWidth() as forwarding functions.  Expanded
  792.  * GetMetric() to handle all cases
  793.  *
  794.  * Revision 1.7  2003/09/25 17:48:19  dicuccio
  795.  * Added API for checking font metrics (only height is supported)
  796.  *
  797.  * Revision 1.6  2003/09/24 15:59:39  rsmith
  798.  * in CGlBitmapFont::SetFont use GLsizei consistently to prevent max template from complaining about being passed arguments with different types.
  799.  *
  800.  * Revision 1.5  2003/09/17 16:25:12  dicuccio
  801.  * Added new functions to handle automatic alignment, trimming of text.  Optimized
  802.  * and correctly implemented TextHeight()
  803.  *
  804.  * Revision 1.4  2003/08/28 19:27:54  dicuccio
  805.  * TextOut() functions are now const
  806.  *
  807.  * Revision 1.3  2003/08/22 15:47:12  dicuccio
  808.  * Added display lists to CGlBitmapFont
  809.  *
  810.  * Revision 1.2  2003/08/19 10:32:29  dicuccio
  811.  * Fix compilation error - max<T>() needs to be passed two valuesof the same type
  812.  *
  813.  * Revision 1.1  2003/08/18 19:24:12  dicuccio
  814.  * Initial revision of new bitmap fonts
  815.  *
  816.  * ===========================================================================
  817.  */