00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "OSDLFixedFont.h"
00028
00029 #include "OSDLSurface.h"
00030 #include "OSDLPixel.h"
00031 #include "OSDLVideoTypes.h"
00032 #include "OSDLUtils.h"
00033
00034
00035
00036 #include <list>
00037
00038 #include <ctype.h>
00039
00040
00041
00042 #ifdef OSDL_USES_CONFIG_H
00043 #include <OSDLConfig.h>
00044 #endif // OSDL_USES_CONFIG_H
00045
00046 #if OSDL_ARCH_NINTENDO_DS
00047 #include "OSDLConfigForNintendoDS.h"
00048 #endif // OSDL_ARCH_NINTENDO_DS
00049
00050
00051
00052 #if OSDL_USES_SDL_GFX
00053
00054 #include "SDL_gfxPrimitives.h"
00055
00056 #endif // OSDL_USES_SDL_GFX
00057
00058
00059 #if OSDL_USES_SDL
00060
00061 #include "SDL.h"
00062
00063 #endif // OSDL_USES_SDL
00064
00065
00066
00067
00068 using std::string ;
00069
00070 using namespace Ceylan ;
00071 using namespace Ceylan::Log ;
00072 using namespace Ceylan::System ;
00073
00074 using namespace OSDL::Video ;
00075 using namespace OSDL::Video::Pixels ;
00076 using namespace OSDL::Video::TwoDimensional ;
00077 using namespace OSDL::Video::TwoDimensional::Text ;
00078
00079
00080
00081
00082 Ceylan::System::FileLocator Text::FixedFont::FixedFontFileLocator ;
00083
00084
00085
00086 const OSDL::Video::Length
00087 OSDL::Video::TwoDimensional::Text::BasicFontCharacterWidth = 8 ;
00088
00089 const OSDL::Video::Length
00090 OSDL::Video::TwoDimensional::Text::BasicFontCharacterHeight = 8 ;
00091
00092
00093
00094
00095 string Text::FixedFont::FontFileExtension = ".fnt" ;
00096
00097
00098 const Ceylan::Float32 Text::FixedFont::SpaceWidthFactor = 0.7f ;
00099
00100
00101 const Ceylan::Uint16 Text::FixedFont::FontCharacterCount = 256 ;
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 bool Text::printBasic( const std::string & text, Surface & targetSurface,
00112 Coordinate x, Coordinate y, Pixels::ColorDefinition colorDef )
00113 {
00114
00115 #if OSDL_USES_SDL_GFX
00116
00117 FixedFont::SetFontSettings( 0, 8,
00118 8 ) ;
00119
00120 bool result = ::stringColor( & targetSurface.getSDLSurface(),
00121 x, y, text.c_str(),
00122 Pixels::convertColorDefinitionToRawPixelColor( colorDef ) ) == 0 ;
00123
00124 return result ;
00125
00126 #else // OSDL_USES_SDL_GFX
00127
00128 throw VideoException( "Text::printBasic failed: "
00129 "no SDL_gfx support available" ) ;
00130
00131 #endif // OSDL_USES_SDL_GFX
00132
00133 }
00134
00135
00136
00137 bool Text::printBasic( const std::string & text, Surface & targetSurface,
00138 Coordinate x, Coordinate y,
00139 Pixels::ColorElement red, Pixels::ColorElement blue,
00140 Pixels::ColorElement green, Pixels::ColorElement alpha )
00141 {
00142
00143 #if OSDL_USES_SDL_GFX
00144
00145 FixedFont::SetFontSettings( 0, 8,
00146 8 ) ;
00147
00148
00149
00150
00151
00152
00153
00154 bool result = ::stringRGBA( & targetSurface.getSDLSurface(), x, y,
00155 text.c_str(), red, green, blue, alpha ) == 0 ;
00156
00157 return result ;
00158
00159 #else // OSDL_USES_SDL_GFX
00160
00161 throw VideoException( "Text::printBasic failed: "
00162 "no SDL_gfx support available" ) ;
00163
00164 #endif // OSDL_USES_SDL_GFX
00165
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 FixedFont::FixedFont(
00186 Length characterWidth,
00187 Length characterHeight,
00188 RenderingStyle renderingStyle,
00189 bool convertToDisplay,
00190 RenderCache cacheSettings,
00191 AllowedCachePolicy cachePolicy,
00192 Ceylan::System::Size quota ) :
00193 Font( convertToDisplay, cacheSettings, cachePolicy, quota ),
00194 _width( characterWidth ),
00195 _height( characterHeight ),
00196 _fontData( 0 )
00197 {
00198
00199
00200 loadFontFrom( BuildFontFilenameFor( characterWidth, characterHeight,
00201 renderingStyle ) ) ;
00202
00203 }
00204
00205
00206
00207 FixedFont::FixedFont(
00208 const std::string & fontFilename,
00209 bool convertToDisplay,
00210 RenderCache cacheSettings,
00211 AllowedCachePolicy cachePolicy,
00212 Ceylan::System::Size quota ) :
00213 Font( convertToDisplay, cacheSettings, cachePolicy, quota ),
00214 _width( 0 ),
00215 _height( 0 ),
00216 _fontData( 0 )
00217 {
00218
00219 GetFontAttributesFrom( fontFilename, _width, _height, _renderingStyle ) ;
00220
00221
00222 loadFontFrom( fontFilename ) ;
00223
00224 }
00225
00226
00227
00228 FixedFont::~FixedFont() throw()
00229 {
00230
00231 if ( _fontData != 0 )
00232 delete [] _fontData ;
00233
00234 }
00235
00236
00237
00238 Width FixedFont::getWidth() const
00239 {
00240
00241 return _width ;
00242
00243 }
00244
00245
00246
00247 Width FixedFont::getWidth( Ceylan::Latin1Char character ) const
00248 {
00249
00250 return _width ;
00251
00252 }
00253
00254
00255
00256 SignedWidth FixedFont::getWidthOffset( Ceylan::Latin1Char character ) const
00257 {
00258
00259 return 0 ;
00260
00261 }
00262
00263
00264
00265 SignedHeight FixedFont::getHeightAboveBaseline( Ceylan::Latin1Char character )
00266 const
00267 {
00268
00269 return _height ;
00270
00271 }
00272
00273
00274
00275 SignedLength FixedFont::getAdvance() const
00276 {
00277
00278 return _width ;
00279
00280 }
00281
00282
00283
00284 SignedLength FixedFont::getAdvance( Ceylan::Latin1Char character ) const
00285 {
00286
00287
00288 return _width ;
00289
00290 }
00291
00292
00293
00294 Width FixedFont::getInterGlyphWidth() const
00295 {
00296
00297 return 0 ;
00298
00299 }
00300
00301
00302
00303 Text::Height FixedFont::getHeight() const
00304 {
00305
00306 return _height ;
00307
00308 }
00309
00310
00311
00312 SignedHeight FixedFont::getAscent() const
00313 {
00314 return _height ;
00315 }
00316
00317
00318
00319 SignedHeight FixedFont::getDescent() const
00320 {
00321
00322 return 0 ;
00323
00324 }
00325
00326
00327
00328 Text::Height FixedFont::getLineSkip() const
00329 {
00330
00331 return _height + static_cast<Text::Height>(
00332 Ceylan::Maths::Max<Ceylan::Float32>( 2, 0.1f * _height ) ) ;
00333
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343 UprightRectangle & FixedFont::getBoundingBox() const
00344 {
00345
00346 return * new UprightRectangle( 0, 0, getAdvance(), getLineSkip() ) ;
00347
00348 }
00349
00350
00351
00352 UprightRectangle & FixedFont::getBoundingBoxFor( const std::string & word )
00353 const
00354 {
00355
00356 if ( word.empty() )
00357 throw FontException(
00358 "FixedFont::getBoundingBoxFor (word): empty word specified." ) ;
00359
00360 return * new UprightRectangle( 0, 0,
00361 static_cast<Length>( getAdvance() * ( word.size() - 1 ) + _width ),
00362 static_cast<Length>( _height ) ) ;
00363
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 OSDL::Video::Surface & FixedFont::renderLatin1Glyph(
00375 Ceylan::Latin1Char character, RenderQuality quality,
00376 Pixels::ColorDefinition glyphColor )
00377 {
00378
00379
00380
00381 if ( _cacheSettings == GlyphCached )
00382 {
00383
00384
00385
00386
00387
00388
00389
00390 CharColorQualityKey renderKey( character, glyphColor,
00391 DefaultQuality ) ;
00392
00393 SmartResource * res = _glyphCache->getClone( renderKey ) ;
00394
00395 if ( res != 0 )
00396 {
00397
00398 Surface * toReturn = dynamic_cast<Surface *>( res ) ;
00399
00400 #if OSDL_DEBUG_FONT
00401
00402 LogPlug::debug( "FixedFont::renderLatin1Glyph: cache hit, "
00403 "returning clone of prerendered glyph." ) ;
00404
00405 if ( toReturn == 0 )
00406 Ceylan::emergencyShutdown( "FixedFont::renderLatin1Glyph: "
00407 "cache did not return a Surface." ) ;
00408
00409 #endif // OSDL_DEBUG_FONT
00410
00411 return *toReturn ;
00412
00413 }
00414
00415
00416 #if OSDL_DEBUG_FONT
00417
00418 LogPlug::debug( "FixedFont::renderLatin1Glyph: "
00419 "cache miss, creating new glyph rendering." ) ;
00420
00421 #endif // OSDL_DEBUG_FONT
00422
00423
00424 Surface & newSurface = basicRenderLatin1Glyph( character, glyphColor ) ;
00425
00426
00427 _glyphCache->scanForAddition( renderKey, newSurface ) ;
00428
00429
00430 return newSurface ;
00431
00432 }
00433
00434
00435
00436
00437
00438
00439 return basicRenderLatin1Glyph( character, glyphColor ) ;
00440
00441 }
00442
00443
00444
00445 void FixedFont::blitLatin1Glyph( Surface & targetSurface,
00446 Coordinate x, Coordinate y,
00447 Ceylan::Latin1Char character, RenderQuality quality,
00448 Pixels::ColorDefinition glyphColor )
00449 {
00450
00451
00452
00453
00454
00455
00456 if ( _cacheSettings == GlyphCached )
00457 {
00458
00459
00460
00461
00462
00463
00464
00465 CharColorQualityKey renderKey( character, glyphColor,
00466 DefaultQuality ) ;
00467
00468 const Resource * cacheEntry = _glyphCache->get( renderKey ) ;
00469
00470 if ( cacheEntry != 0 )
00471 {
00472
00473
00474 const Surface * cachedSurface =
00475 dynamic_cast<const Surface *>( cacheEntry ) ;
00476
00477 #if OSDL_DEBUG_FONT
00478
00479 LogPlug::debug( "FixedFont::blitLatin1Glyph: "
00480 "cache hit, blitting prerendered glyph." ) ;
00481
00482 if ( cachedSurface == 0 )
00483 Ceylan::emergencyShutdown( "FixedFont::blitLatin1Glyph: "
00484 "cache did not return a Surface." ) ;
00485
00486 #endif // OSDL_DEBUG_FONT
00487
00488 try
00489 {
00490
00491 cachedSurface->blitTo( targetSurface, x, y ) ;
00492
00493 }
00494 catch( const VideoException & e )
00495 {
00496 throw FontException( "FixedFont::blitLatin1Glyph: "
00497 "blit of cloned glyph failed: " + e.toString() ) ;
00498 }
00499
00500 }
00501 else
00502 {
00503
00504 #if OSDL_DEBUG_FONT
00505
00506 LogPlug::debug( "FixedFont::blitLatin1Glyph: cache miss, "
00507 "blitting newly rendered glyph." ) ;
00508
00509 #endif // OSDL_DEBUG_FONT
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 submitLatin1GlyphToCache( character, glyphColor ).blitTo(
00521 targetSurface, x, y ) ;
00522
00523 }
00524
00525 }
00526
00527
00528
00529
00530
00531
00532 basicBlitLatin1Glyph( targetSurface, x, y, character, glyphColor ) ;
00533
00534 }
00535
00536
00537
00538 OSDL::Video::Surface & FixedFont::renderLatin1GlyphAlpha(
00539 Ceylan::Latin1Char character, RenderQuality quality,
00540 Pixels::ColorDefinition glyphColor )
00541 {
00542
00543 #if OSDL_USES_SDL_GFX
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 Pixels::PixelColor color = Pixels::convertColorDefinitionToRawPixelColor(
00566 glyphColor ) ;
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 Surface & res = * new Surface( * SDL_CreateRGBSurface(
00621 Surface::Hardware, _width, _height, 32,
00622 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF0
00623
00624 ) ) ;
00625
00626
00627 res.setAlpha( 0 ,
00628 Pixels::AlphaOpaque ) ;
00629
00630
00631 if ( ::characterColor( & res.getSDLSurface(), 0, 0,
00632 static_cast<char>( character ), color ) != 0 )
00633 throw FontException( "FixedFont::renderLatin1Glyph: blit failed, "
00634 + Utils::getBackendLastError() ) ;
00635
00636
00637 res.setAlpha( Surface::AlphaBlendingBlit, Pixels::AlphaOpaque ) ;
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 return res ;
00648
00649 #else // OSDL_USES_SDL_GFX
00650
00651 throw FontException( "FixedFont::renderLatin1GlyphAlpha failed: "
00652 "no SDL_gfx support available" ) ;
00653
00654 #endif // OSDL_USES_SDL_GFX
00655
00656 }
00657
00658
00659
00660 const string FixedFont::toString( Ceylan::VerbosityLevels level ) const
00661 {
00662
00663 string res = "Fixed font, whose dimensions are "
00664 + Ceylan::toString( _width )
00665 + "x" + Ceylan::toString( _height ) ;
00666
00667 if ( level == Ceylan::low )
00668 return res ;
00669
00670 res += ". " + Font::toString( level ) ;
00671
00672 return res ;
00673
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 Font::RenderQuality FixedFont::GetObtainedQualityFor(
00688 Font::RenderQuality targetedQuality )
00689 {
00690
00691 return Solid ;
00692
00693 }
00694
00695
00696
00697 void FixedFont::SetFontSettings( const Ceylan::Byte * fontData,
00698 Length characterWidth, Length characterHeight )
00699 {
00700
00701 #if OSDL_USES_SDL_GFX
00702
00703 static const char * lastFontData = 0 ;
00704 static Length lastCharacterWidth = 0 ;
00705 static Length lastCharacterHeight = 0 ;
00706
00707
00708
00709
00710
00711
00712 if ( lastFontData != fontData || lastCharacterWidth != characterWidth
00713 || lastCharacterHeight != characterHeight )
00714 {
00715
00716
00717
00718 #if OSDL_DEBUG_FONT
00719
00720 LogPlug::debug(
00721 "FixedFont::SetFontSettings: having to reset SDL_gfx state" ) ;
00722
00723 #endif // OSDL_DEBUG_FONT
00724
00725 lastFontData = fontData ;
00726 lastCharacterWidth = characterWidth ;
00727 lastCharacterHeight = characterHeight ;
00728
00729 gfxPrimitivesSetFont( fontData, characterWidth, characterHeight ) ;
00730 }
00731 else
00732 {
00733
00734 #if OSDL_DEBUG_FONT
00735
00736 LogPlug::debug( "FixedFont::SetFontSettings: saved a SDL_gfx reset" ) ;
00737
00738 #endif // OSDL_DEBUG_FONT
00739
00740 }
00741
00742 #else // OSDL_USES_SDL_GFX
00743
00744 throw FontException( "FixedFont::SetFontSettings failed: "
00745 "no SDL_gfx support available" ) ;
00746
00747 #endif // OSDL_USES_SDL_GFX
00748
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758 void FixedFont::loadFontFrom( const std::string & fontFilename )
00759 {
00760
00761 #if OSDL_DEBUG_FONT
00762
00763 LogPlug::trace( "FixedFont::loadFontFrom: trying to load font file '"
00764 + fontFilename + "'." ) ;
00765
00766 #endif // OSDL_DEBUG_FONT
00767
00768 string fontFullPath = fontFilename ;
00769
00770
00771 if ( ! File::ExistsAsFileOrSymbolicLink( fontFilename ) )
00772 {
00773
00774 try
00775 {
00776
00777 fontFullPath = FixedFontFileLocator.find( fontFilename ) ;
00778 }
00779 catch( const System::FileLocatorException & e )
00780 {
00781
00782
00783 try
00784 {
00785 fontFullPath = Font::FontFileLocator.find( fontFilename ) ;
00786 }
00787 catch( const System::FileLocatorException & ex )
00788 {
00789
00790
00791
00792 string currentDir ;
00793
00794 try
00795 {
00796 currentDir = Directory::GetCurrentWorkingDirectoryPath() ;
00797 }
00798 catch( const DirectoryException & exc )
00799 {
00800
00801 throw FontException(
00802 "FixedFont::loadFontFrom: unable to load '"
00803 + fontFilename
00804 + "', exception generation triggered another failure: "
00805 + exc.toString() + "." ) ;
00806
00807 }
00808
00809 throw FontException( "FixedFont::loadFontFrom: '"
00810 + fontFilename
00811 + "' is not a regular file or a symbolic link "
00812 "relative to the current directory (" + currentDir
00813 + ") and cannot be found through Fixed font locator ("
00814 + FixedFont::FixedFontFileLocator.toString()
00815 + ") nor through general font locator "
00816 "based on font path environment variable ("
00817 + Font::FontPathEnvironmentVariable + "): "
00818 + Font::FontFileLocator.toString() + "." ) ;
00819
00820 }
00821 }
00822 }
00823
00824
00825
00826
00827 #if OSDL_DEBUG_FONT
00828
00829 LogPlug::debug( "FixedFont::loadFontFrom: full font filename is '"
00830 + fontFullPath + "'." ) ;
00831
00832 #endif // OSDL_DEBUG_FONT
00833
00834 try
00835 {
00836
00837 Ceylan::Holder<File> fontFile(
00838 File::Open( fontFullPath ) ) ;
00839
00840 System::Size dataSize = fontFile->size() ;
00841
00842 if ( _fontData != 0 )
00843 delete [] _fontData ;
00844
00845 _fontData = new char[ dataSize ] ;
00846
00847 if ( _fontData == 0 )
00848 throw FontException(
00849 "FixedFont::loadFontFrom: not enough memory." ) ;
00850
00851 fontFile->readExactLength( _fontData, dataSize ) ;
00852
00853
00854
00855 }
00856 catch( const System::SystemException & e )
00857 {
00858
00859 throw FontException( "FixedFont::loadFontFrom: "
00860 "error while loading font data file: " + e.toString() ) ;
00861 }
00862
00863 _spaceWidth = static_cast<Width>( SpaceWidthFactor *
00864 getWidth( ) ) ;
00865
00866
00867 _alineaWidth = DefaultSpaceBasedAlineaWidth * _spaceWidth ;
00868
00869
00870
00871 }
00872
00873
00874
00875 const Surface & FixedFont::submitLatin1GlyphToCache(
00876 Ceylan::Latin1Char character, Pixels::ColorDefinition glyphColor )
00877 {
00878
00879
00880
00881
00882
00883
00884 Surface & glyphSurface = basicRenderLatin1Glyph( character, glyphColor ) ;
00885
00886 CharColorQualityKey renderKey( character, glyphColor,
00887 DefaultQuality ) ;
00888
00889 bool takenByCache ;
00890
00891 try
00892 {
00893 takenByCache = _glyphCache->takeOwnershipOf( renderKey, glyphSurface ) ;
00894 }
00895 catch( const ResourceManagerException & e )
00896 {
00897
00898
00899
00900
00901
00902
00903
00904 throw FontException(
00905 "FixedFont::submitLatin1GlyphToCache: cache submitting failed: "
00906 + e.toString() ) ;
00907
00908 }
00909
00910 if ( ! takenByCache )
00911 throw FontException( "FixedFont::submitLatin1GlyphToCache: "
00912 "cache did not accept rendering for '"
00913 + Ceylan::toString( character ) + "'." ) ;
00914
00915
00916 return glyphSurface ;
00917
00918 }
00919
00920
00921
00922 Surface & FixedFont::basicRenderLatin1Glyph( Ceylan::Latin1Char character,
00923 Pixels::ColorDefinition glyphColor )
00924 {
00925
00926 ColorMask redMask, greenMask, blueMask ;
00927
00928 Pixels::getRecommendedColorMasks( redMask, greenMask, blueMask ) ;
00929
00930
00931 Surface & res = * new Surface( Surface::Hardware | Surface::ColorkeyBlit,
00932 _width, _height, 32, redMask, greenMask, blueMask,
00933 0 ) ;
00934
00935
00936 Pixels::ColorDefinition colorKey ;
00937
00938 if ( Pixels::areEqual( glyphColor, Pixels::Black, false ) )
00939 {
00940 colorKey = Pixels::White ;
00941 res.fill( colorKey ) ;
00942 }
00943 else
00944 {
00945
00946 colorKey = Pixels::Black ;
00947
00948
00949
00950
00951
00952
00953
00954 }
00955
00956 basicBlitLatin1Glyph( res, 0, 0, character, glyphColor ) ;
00957
00958
00959 res.setColorKey( Surface::ColorkeyBlit | Surface::RLEColorkeyBlit,
00960 convertColorDefinitionToPixelColor( res.getPixelFormat(), colorKey ) ) ;
00961
00962 if ( _convertToDisplay )
00963 {
00964
00965
00966
00967
00968
00969
00970 res.convertToDisplay( false ) ;
00971 }
00972
00973 return res ;
00974
00975 }
00976
00977
00978
00979 void FixedFont::basicBlitLatin1Glyph( Surface & targetSurface,
00980 Coordinate x, Coordinate y, Ceylan::Latin1Char character,
00981 Pixels::ColorDefinition glyphColor )
00982 {
00983
00984 #if OSDL_USES_SDL_GFX
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994 SetFontSettings( _fontData, _width, _height ) ;
00995
00996 Pixels::PixelColor color = Pixels::convertColorDefinitionToRawPixelColor(
00997 glyphColor ) ;
00998
00999 if ( ::characterColor( & targetSurface.getSDLSurface(), x, y,
01000 static_cast<char>( character ), color ) != 0 )
01001 throw FontException(
01002 "FixedFont::basicBlitLatin1Glyph: blit of glyph failed, "
01003 + Utils::getBackendLastError() ) ;
01004
01005 #else // OSDL_USES_SDL_GFX
01006
01007 throw FontException( "FixedFont::basicBlitLatin1Glyph failed: "
01008 "no SDL_gfx support available" ) ;
01009
01010 #endif // OSDL_USES_SDL_GFX
01011
01012 }
01013
01014
01015
01016 string FixedFont::BuildFontFilenameFor(
01017 Length characterWidth, Length characterHeight,
01018 RenderingStyle renderingStyle )
01019 {
01020
01021 string attribute ;
01022
01023 if ( renderingStyle & Bold )
01024 {
01025
01026 if ( renderingStyle & ~Bold )
01027 throw FontException( "FixedFont::BuildFontFilenameFor: "
01028 "too many rendering styles selected: "
01029 + Ceylan::toString( renderingStyle ) + "." ) ;
01030
01031 attribute += "B" ;
01032
01033 }
01034
01035 if ( renderingStyle & Italic )
01036 {
01037
01038 if ( renderingStyle & ~Italic )
01039 throw FontException( "FixedFont::BuildFontFilenameFor: "
01040 "too many rendering styles selected: "
01041 + Ceylan::toString( renderingStyle ) + "." ) ;
01042
01043 attribute += "O" ;
01044
01045 }
01046
01047 if ( renderingStyle & Underline )
01048 {
01049
01050 if ( renderingStyle & ~Underline )
01051 throw FontException( "FixedFont::BuildFontFilenameFor: "
01052 "too many rendering styles selected: "
01053 + Ceylan::toString( renderingStyle ) + "." ) ;
01054
01055 attribute += "U" ;
01056
01057 }
01058
01059
01060 return Ceylan::toString( characterWidth ) + "x"
01061 + Ceylan::toString( characterHeight ) + attribute + FontFileExtension ;
01062
01063 }
01064
01065
01066
01067 void FixedFont::GetFontAttributesFrom( const string & filename,
01068 Length & characterWidth, Length & characterHeight,
01069 RenderingStyle & renderingStyle )
01070 {
01071
01072
01073 System::Size size = filename.size() ;
01074
01075 if ( filename.substr( size - 4 ) != FontFileExtension )
01076 throw FontException(
01077 "FixedFont::GetFontAttributesFrom: expected extension ("
01078 + FontFileExtension + "), not found in '" + filename + "'." ) ;
01079
01080 string width, height ;
01081
01082 Ceylan::Uint16 index = 0 ;
01083
01084 while ( filename[index] != 'x' && index < size - 4 )
01085 {
01086 width += filename[index] ;
01087 }
01088
01089 try
01090 {
01091 characterWidth = static_cast<Length>( stringToUnsignedLong( width ) ) ;
01092 }
01093 catch( const Ceylan::Exception & e )
01094 {
01095
01096 throw FontException(
01097 "FixedFont::GetFontAttributesFrom: unable to guess width from '"
01098 + filename + "': " + e.toString() ) ;
01099 }
01100
01101 index++ ;
01102
01103 while ( ::isdigit( filename[index] )
01104 && index < size - 3 )
01105 {
01106 height += filename[index] ;
01107 }
01108
01109
01110 try
01111 {
01112 characterHeight =
01113 static_cast<Length>( stringToUnsignedLong( height ) ) ;
01114 }
01115 catch( const Ceylan::Exception & e )
01116 {
01117 throw FontException(
01118 "FixedFont::GetFontAttributesFrom: unable to guess height from '"
01119 + filename + "': " + e.toString() ) ;
01120 }
01121
01122
01123 switch( filename[index] )
01124 {
01125
01126 case '.':
01127
01128 renderingStyle = Normal ;
01129 break ;
01130
01131 case 'B':
01132 renderingStyle = Bold ;
01133 break ;
01134
01135 case 'O':
01136 renderingStyle = Italic ;
01137 break ;
01138
01139 case 'U':
01140 renderingStyle = Underline ;
01141 break ;
01142
01143 default:
01144 throw FontException( "FixedFont::getFontAttributesFrom: "
01145 "unable to guess rendering style from '" + filename + "'." ) ;
01146 break ;
01147
01148 }
01149
01150 }
01151