opennurbs_font.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018 
00019 ON_OBJECT_IMPLEMENT( ON_Font, ON_Object, "4F0F51FB-35D0-4865-9998-6D2C6A99721D" );
00020 
00021 ON_Font::ON_Font()
00022 {
00023   Defaults();
00024 }
00025 
00026 ON_Font::~ON_Font()
00027 {
00028 }
00029 
00030 bool ON_Font::CreateFontFromFaceName( 
00031   const wchar_t* facename,
00032   bool bBold,
00033   bool bItalic 
00034   )
00035 {
00036   PurgeUserData();
00037   Defaults();
00038 
00039   if ( 0 == facename || 0 == facename[0] )
00040     facename = L"Arial";
00041 
00042   bool rc = SetFontFaceName(facename);
00043 
00044   HeightOfI();
00045 
00046   m_font_name = facename;
00047   if ( bBold )
00048   {
00049     SetBold(true);
00050     m_font_name += "L Bold";
00051   }
00052   if ( bItalic )
00053   {
00054     SetItalic(true);
00055     m_font_name += "L Italic";
00056   }
00057 
00058   return rc;
00059 }
00060 
00061 
00062 void ON_Font::Defaults()
00063 {
00064   m_font_name.Empty();
00065   m_font_weight = ON_Font::normal_weight;
00066   m_font_italic = false;
00067   m_font_underlined = false;
00068   m_linefeed_ratio = m_default_linefeed_ratio;
00069   m_font_index = -1;
00070   memset(&m_font_id,0,sizeof(m_font_id));
00071   memset( &m_facename, 0, sizeof( m_facename));
00072   m_I_height = 0;
00073 #if defined(ON_OS_WINDOWS_GDI)
00074   memset(&m_logfont,0,sizeof(m_logfont));
00075   m_logfont.lfHeight = normal_font_height;
00076   m_logfont.lfCharSet = default_charset;
00077 #endif
00078   SetFontFaceName(L"Arial");
00079 }
00080 
00082 //
00083 // ON_Object overrides
00084 
00085 ON_BOOL32 ON_Font::IsValid( ON_TextLog* text_log ) const
00086 {
00087   return ( m_font_name.Length() > 0 
00088            && m_font_index >= 0 
00089            && m_facename[0] > 32 
00090            && m_facename[64] == 0
00091            );
00092 }
00093 
00094 void ON_Font::Dump( ON_TextLog& dump ) const
00095 {
00096   const wchar_t* name = FontName();
00097   if ( !name )
00098     name = L"";
00099   dump.Print("font index = %d\n",m_font_index);
00100   dump.Print("font name = \"%ls\"\n",name);
00101   dump.Print("font face name = \"%ls\"\n",m_facename);
00102   dump.Print("font weight = \"%d\"\n",m_font_weight);
00103   dump.Print("font is italic = \"%d\"\n",m_font_italic);
00104   dump.Print("font is underlined = \"%d\"\n",m_font_underlined);
00105   dump.Print("font linefeed ratio = \"%g\"\n", m_linefeed_ratio);
00106 }
00107 
00108 ON_BOOL32 ON_Font::Write(
00109        ON_BinaryArchive& file // serialize definition to binary archive
00110      ) const
00111 {
00112   bool rc = file.Write3dmChunkVersion(1,2);
00113   while(rc)
00114   {
00115     rc = file.WriteInt(m_font_index);
00116     if  (!rc) break;
00117     rc = file.WriteString(m_font_name);
00118     if  (!rc) break;
00119     {
00120       // 18 October 2002 Dale Lear:
00121       //   Lowell, wchar_t has different sizes on different OSs.
00122       //   When writing a wchar_t string, you should use one
00123       //   of the WriteString functions.  This function must continue
00124       //   to use WriteShort(64,...) so old files will remain valid.
00125       unsigned short sh[64];
00126       memset(sh,0,sizeof(sh));
00127       int i;
00128       for ( i = 0; i < 64 && i < face_name_size-1; i++ )
00129         sh[i] = m_facename[i];
00130       rc = file.WriteShort(64, sh);
00131       if  (!rc) break;
00132     }
00133 
00134     // 1.1 additions
00135     rc = file.WriteInt( m_font_weight);
00136     if  (!rc) break;
00137     rc = file.WriteInt( m_font_italic);
00138     if  (!rc) break;
00139     rc = file.WriteDouble( m_linefeed_ratio);
00140     if  (!rc) break;
00141 
00142     // 1.2 addition
00143     rc = file.WriteUuid( m_font_id);
00144     if (!rc) break;
00145 
00146     // 1.3 addition
00147 //    rc = file.WriteInt( m_font_underlined);
00148 //    if  (!rc) break;
00149 
00150     break;
00151   }
00152 
00153   return rc;
00154 }
00155 
00156 ON_BOOL32 ON_Font::Read(
00157        ON_BinaryArchive& file // restore definition from binary archive
00158      )
00159 {
00160   Defaults();
00161   m_font_index = -1;
00162   int major_version = 0;
00163   int minor_version = 0;
00164   bool rc = file.Read3dmChunkVersion(&major_version,&minor_version);
00165   if ( rc && major_version == 1 ) 
00166   {
00167     int i;
00168     for(;;)
00169     {
00170       rc = file.ReadInt( &m_font_index );
00171       if  (!rc) break;
00172       rc = file.ReadString( m_font_name );
00173       if  (!rc) break;
00174 
00175       {
00176         // 18 October 2002 Dale Lear:
00177         //   Lowell, wchar_t has different sizes on different OSs.
00178         //   When writing a wchar_t string, you should use one
00179         //   of the WriteString functions.  This function must continue
00180         //   to use ReadShort(64,...) so old files will remain valid.
00181         unsigned short sh[64];
00182         rc = file.ReadShort(64, sh);
00183         if (!rc) break;
00184 
00185         wchar_t facename[65];
00186         for ( i = 0; i < 64; i++ )
00187         {
00188           facename[i] = sh[i];
00189         }
00190         facename[64] = 0;
00191         SetFontFaceName(facename);
00192       }
00193 
00194       if( minor_version >= 1 )
00195       {
00196         rc = file.ReadInt( &i );
00197         if (!rc) break;
00198         SetFontWeight(i);
00199 
00200         rc = file.ReadInt( &i);
00201         if (!rc) break;
00202         SetIsItalic(i?true:false);
00203 
00204         rc = file.ReadDouble( &m_linefeed_ratio );
00205         if (!rc) break;
00206 
00207         if ( minor_version >= 2 )
00208         {
00209           rc = file.ReadUuid( m_font_id );
00210           if (!rc) break;
00211         }
00212         //if ( minor_version >= 3 )
00213         //{
00214         //  rc = file.ReadInt( &i);
00215         //  if (!rc) break;
00216         //  SetUnderlined(i?true:false);
00217         //}
00218       }
00219 
00220       break;
00221     }
00222   }
00223   else
00224   {
00225     ON_ERROR("ON_Font::Read - get newer version of opennurbs");
00226     rc = false;
00227   }
00228 
00229   return rc;
00230 }
00231 
00232 // Ratio of linefeed to character height
00233 const double ON_Font::m_default_linefeed_ratio = 1.6;
00234 
00235 // This must be an 'I' or 'H', but we have not tested 'H'.
00236 // There are problems with any other upper case character.
00237 // In particular, the standard 'M' does not work.
00238 const int ON_Font::m_metrics_char = 'I';
00239 
00241 //
00242 // Interface
00243 void ON_Font::SetFontName( const wchar_t* s )
00244 {
00245   m_font_name = s;
00246 }
00247 
00248 void ON_Font::SetFontName( const char* s )
00249 {
00250   m_font_name = s;
00251 }
00252 
00253 void ON_Font::GetFontName( ON_wString& s ) const
00254 {
00255   s = m_font_name;
00256 }
00257 
00258 const wchar_t* ON_Font::FontName() const
00259 {
00260   const wchar_t* s = m_font_name;
00261   return s;
00262 }
00263 
00264 #if defined(ON_OS_WINDOWS_GDI)
00265 static 
00266 int CALLBACK ON__IsSymbolFontFaceNameHelper( ENUMLOGFONTEX*, NEWTEXTMETRICEX*, DWORD, LPARAM)
00267 {
00268   // If the fontname in the logfont structure has
00269   // a corresponding symbol font on the system, 
00270   // set the  lfCharSet member to SYMBOL_CHARSET, 
00271   // otherwise DEFAULT_CHARSET
00272   // The input logfont structure may be modified.
00273   return 7;
00274 }
00275 #endif
00276 
00277 bool ON_Font::IsSymbolFontFaceName( const wchar_t* s)
00278 {
00279   bool rc = false;
00280 
00281 #if defined(ON_OS_WINDOWS_GDI)
00282   if( s && s[0])
00283   {
00284     HDC hdc = ::GetDC( NULL);    
00285     if( hdc)
00286     {      
00287       LOGFONT logfont;
00288       memset( &logfont, 0, sizeof( logfont));
00289       int i;
00290       for ( i = 0; i < LF_FACESIZE && s[i]; i++ )
00291       {
00292         logfont.lfFaceName[i] = s[i];
00293       }
00294       logfont.lfCharSet = ON_Font::symbol_charset;
00295       if( 7 == ::EnumFontFamiliesEx( hdc, &logfont, (FONTENUMPROC)ON__IsSymbolFontFaceNameHelper, 0, 0))
00296       {
00297         rc = true;
00298       }    
00299       ::ReleaseDC( NULL, hdc);
00300     }
00301   }
00302 #endif
00303 
00304   return rc;
00305 }
00306 
00307 bool ON_Font::SetFontFaceName( const wchar_t* s )
00308 {
00309   int i;
00310   memset( &m_facename, 0, sizeof(m_facename) );
00311   if ( s)
00312   {
00313     for ( i = 0; i < face_name_size-1 && s[i]; i++ )
00314     {
00315       m_facename[i] = s[i];
00316     }
00317   }
00318 
00319 #if defined(ON_OS_WINDOWS_GDI)
00320   memset( &m_logfont.lfFaceName, 0, sizeof(m_logfont.lfFaceName) );
00321 #endif
00322 
00323   m_I_height = 0;
00324 
00325   UpdateImplementationSettings();
00326 
00327   return( m_facename[0] ? true : false);
00328 }
00329 
00330 bool ON_Font::SetFontFaceName( const char* s )
00331 {
00332   ON_wString wstr(s);
00333   const wchar_t* w = wstr;
00334   return SetFontFaceName(w);
00335 }
00336 
00337 double ON_Font::AscentRatio() const
00338 {
00339   return ((double)normal_font_height) / ((double)HeightOfI());
00340 }
00341 
00342 void ON_Font::GetFontFaceName( ON_wString& s ) const
00343 {
00344   s = m_facename;
00345 }
00346 
00347 const wchar_t* ON_Font::FontFaceName() const
00348 {
00349   const wchar_t* s = m_facename;
00350   return s;
00351 }
00352 
00353 void ON_Font::SetFontIndex(int i)
00354 {
00355   m_font_index = i;
00356 }
00357 
00358 int ON_Font::FontIndex() const
00359 {
00360   return m_font_index;
00361 }
00362 
00363 double ON_Font::LinefeedRatio() const
00364 {
00365   return m_linefeed_ratio;
00366 }
00367 
00368 void ON_Font::SetLinefeedRatio( double d)
00369 {
00370   m_linefeed_ratio = d;
00371 }
00372 
00373 int ON_Font::FontWeight() const
00374 {
00375   return m_font_weight;
00376 }
00377 
00378 void ON_Font::SetFontWeight( int w)
00379 {
00380   if ( w != m_font_weight )
00381   {
00382     if ( w < 0 )
00383       w = 0;
00384     m_font_weight = w;
00385     m_I_height = 0;
00386     UpdateImplementationSettings();
00387   }
00388 }
00389 
00390 bool ON_Font::IsItalic() const
00391 {
00392   return m_font_italic;
00393 }
00394 
00395 void ON_Font::SetIsItalic( bool b)
00396 {
00397   SetItalic( b);
00398 }
00399 
00400 
00401 void ON_Font::SetItalic( bool b)
00402 {
00403   if ( m_font_italic != b )
00404   {
00405     m_font_italic = b?true:false;
00406     m_I_height = 0;
00407     UpdateImplementationSettings();
00408   }
00409 }
00410 
00411 bool ON_Font::IsBold() const
00412 {
00413   return (FontWeight() >= bold_weight);
00414 }
00415 
00416 
00417 void ON_Font::SetBold( bool bBold )
00418 {
00419   SetFontWeight( bBold ? bold_weight : normal_weight);
00420 }
00421 
00422 
00423 bool ON_Font::IsUnderlined() const
00424 {
00425   return m_font_underlined;
00426 }
00427 
00428 
00429 void ON_Font::SetUnderlined( bool b)
00430 {
00431   if ( m_font_underlined != b )
00432   {
00433     m_font_underlined = b?true:false;
00434     UpdateImplementationSettings();
00435   }
00436 }
00437 
00438 void ON_Font::UpdateImplementationSettings()
00439 {
00440 #if defined(ON_OS_WINDOWS_GDI) 
00441   BYTE b;
00442   LONG w;
00443   size_t cap0, cap1, cap, i;
00444 
00445   w = m_font_weight;
00446   if ( w < 0 )
00447     w = 0;
00448   if ( w != m_logfont.lfWeight )
00449   {
00450     m_logfont.lfWeight = w;
00451     m_I_height = 0;
00452   }
00453 
00454   b = m_font_italic ? 1 : 0;
00455   if ( b != m_logfont.lfItalic )
00456   {
00457     m_logfont.lfItalic = b;
00458     m_I_height = 0;
00459   }
00460 
00461   b = m_font_underlined ? 1 : 0;
00462   if ( b != m_logfont.lfUnderline )
00463   {
00464     m_logfont.lfUnderline = b;
00465     m_I_height = 0;
00466   }
00467 
00468   b = 0;
00469   cap0 = sizeof(m_facename)/sizeof(m_facename[0]);
00470   cap1 = sizeof(m_logfont.lfFaceName)/sizeof(m_logfont.lfFaceName[0]);
00471   cap = cap0 < cap1 ? cap0 : cap1;
00472   for ( i = 0; i < cap; i++ )
00473   {
00474     if ( m_logfont.lfFaceName[i] != m_facename[i] )
00475     {
00476       m_logfont.lfFaceName[i] = m_facename[i];
00477       b = 1;
00478     }
00479   }
00480   if ( b )
00481   {
00482     for ( i = cap; i < cap1; i++ )
00483       m_logfont.lfFaceName[i] = 0;
00484 
00485     m_logfont.lfCharSet = ON_Font::IsSymbolFontFaceName( m_logfont.lfFaceName )
00486                       ? ((unsigned char)ON_Font::symbol_charset)
00487                       : ((unsigned char)ON_Font::default_charset);
00488 
00489     m_I_height = 0;
00490   }
00491   
00492 #endif
00493 }
00494 
00495 /*
00496 Returns:
00497   Height of the 'I' character when the font is drawn 
00498   with m_logfont.lfHeight = 256.
00499 */
00500 int ON_Font::HeightOfI() const
00501 {
00502   if ( m_I_height  <= 0 )
00503   {
00504     // Default is height of Arial 'I'.  If we are running
00505     // on Windows, then we calculate the actual height of
00506     // an 'I' in the font.
00507     //   The ..ON_Font::normal_font_height/256 is here 
00508     //   so this code will continue to work correctly 
00509     //   if somebody changes ON_Font::normal_font_height.
00510     int I_height = (166*ON_Font::normal_font_height)/256;
00511 
00512 #if defined(ON_OS_WINDOWS_GDI)
00513     if ( m_logfont.lfFaceName[0] )
00514     {
00515       // Get the height of an 'I'
00516       HDC hdc = ::GetDC( NULL);
00517       if (hdc)
00518       {
00519         LOGFONT logfont = m_logfont;
00520         logfont.lfHeight = normal_font_height;
00521         HFONT font = ::CreateFontIndirect( &logfont);
00522         if ( font )
00523         {
00524           wchar_t str[2];
00525           str[0] = ON_Font::m_metrics_char;
00526           str[1] = 0;
00527           HFONT oldfont = (HFONT)::SelectObject( hdc, font);
00528           ::SetBkMode( hdc, TRANSPARENT);
00529           ::BeginPath(hdc);
00530           ::ExtTextOut( hdc, 0, 0, 0, NULL, str, 1, NULL);
00531           ::EndPath( hdc);
00532           int numPoints = ::GetPath( hdc, NULL, NULL, 0);
00533 
00534           if( numPoints > 2)
00535           {
00536             // Allocate room for the points & point types
00537             LPPOINT pPoints = (LPPOINT)onmalloc( numPoints * sizeof(*pPoints) );
00538             LPBYTE pTypes = (LPBYTE)onmalloc( numPoints * sizeof(*pTypes) );
00539             if ( pTypes && pPoints)
00540             {
00541               // Get the points and types from the current path
00542               numPoints = ::GetPath( hdc, pPoints, pTypes, numPoints);
00543               if( numPoints > 2)
00544               {
00545                 int ymin = pPoints[0].y;
00546                 int ymax = ymin;
00547                 int k;
00548                 for( k = 1; k < numPoints; k++)
00549                 {
00550                   if( pPoints[k].y < ymin)
00551                     ymin = pPoints[k].y;
00552                   else if( pPoints[k].y > ymax)
00553                     ymax = pPoints[k].y;
00554                 }
00555                 I_height = ymax - ymin + 1;
00556               }
00557             }
00558             onfree( pPoints);
00559             onfree( pTypes);
00560           }
00561           ::SelectObject( hdc, oldfont);
00562           ::DeleteObject( font);
00563         }
00564       }
00565       ::ReleaseDC( NULL, hdc);
00566     }
00567 #endif
00568     const_cast<ON_Font*>(this)->m_I_height = I_height;
00569   }
00570   return m_I_height;
00571 }
00572 
00573 
00574 int ON_Font::HeightOfLinefeed() const
00575 {
00576   return ( (int)( ceil(m_linefeed_ratio*HeightOfI()) ) );
00577 }
00578 
00579 #if defined(ON_OS_WINDOWS_GDI)
00580 
00581 #pragma message( " --- OpenNURBS including Windows LOGFONT support in ON_Font" )
00582 
00583 bool ON_Font::SetLogFont( const LOGFONT& logfont )
00584 {
00585   if ( &m_logfont != &logfont )
00586   {
00587     memcpy(&m_logfont,&logfont,sizeof(m_logfont));
00588   }
00589     
00590   // synch persistent fields
00591   m_font_weight = m_logfont.lfWeight;
00592   m_font_italic = (m_logfont.lfItalic?true:false);
00593   m_font_underlined = (m_logfont.lfUnderline?true:false);
00594   memset(&m_facename[0],0,sizeof(m_facename));
00595   int i;
00596   for ( i = 0; i < face_name_size && i < LF_FACESIZE; i++ )
00597   {
00598     m_facename[i] = (wchar_t)m_logfont.lfFaceName[i]; 
00599   }
00600   m_facename[face_name_size-1] = 0;
00601 
00602 
00603   m_I_height = 0;
00604 
00605   return true;
00606 }
00607 
00608 const LOGFONT& ON_Font::LogFont() const
00609 {
00610   return m_logfont;
00611 }
00612 
00613 ON_Font::ON_Font( const LOGFONT& logfont )
00614 {
00615   Defaults();
00616   SetLogFont(logfont);
00617 }
00618 
00619 ON_Font& ON_Font::operator=( const LOGFONT& logfont )
00620 {
00621   if ( &m_logfont == &logfont )
00622   {
00623     LOGFONT lf = logfont;
00624     SetLogFont(lf);
00625   }
00626   else
00627   {
00628     SetLogFont(logfont);
00629   }
00630   return *this;
00631 }
00632 
00633 bool ON_Font::CompareFontCharacteristics( ON_Font& other_font, bool bCompareName) const
00634 {
00635   if( bCompareName && m_font_name.CompareNoCase( other_font.m_font_name))
00636     return false;
00637 
00638   if( m_font_weight != other_font.m_font_weight)
00639     return false;
00640   
00641   if( m_font_italic != other_font.m_font_italic)
00642     return false;
00643   
00644   if( m_font_underlined != other_font.m_font_underlined)
00645     return false;
00646   
00647   if( m_linefeed_ratio != other_font.m_linefeed_ratio)
00648     return false;
00649   
00650   if( _wcsicmp( m_facename, other_font.m_facename))
00651     return false;
00652 
00653   return true;
00654 }
00655 
00656 
00657 #endif
00658 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:01