00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
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
00121
00122
00123
00124
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
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
00143 rc = file.WriteUuid( m_font_id);
00144 if (!rc) break;
00145
00146
00147
00148
00149
00150 break;
00151 }
00152
00153 return rc;
00154 }
00155
00156 ON_BOOL32 ON_Font::Read(
00157 ON_BinaryArchive& file
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
00177
00178
00179
00180
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
00213
00214
00215
00216
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
00233 const double ON_Font::m_default_linefeed_ratio = 1.6;
00234
00235
00236
00237
00238 const int ON_Font::m_metrics_char = 'I';
00239
00241
00242
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
00269
00270
00271
00272
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
00497
00498
00499
00500 int ON_Font::HeightOfI() const
00501 {
00502 if ( m_I_height <= 0 )
00503 {
00504
00505
00506
00507
00508
00509
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
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
00537 LPPOINT pPoints = (LPPOINT)onmalloc( numPoints * sizeof(*pPoints) );
00538 LPBYTE pTypes = (LPBYTE)onmalloc( numPoints * sizeof(*pTypes) );
00539 if ( pTypes && pPoints)
00540 {
00541
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
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