1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxFont class 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21 // For compilers that support precompilation, includes "wx.h". 
  22 #include "wx/wxprec.h" 
  33 #include "wx/os2/private.h" 
  35 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
) 
  37 #if wxUSE_PORTABLE_FONTS_IN_MSW 
  38     IMPLEMENT_DYNAMIC_CLASS(wxFontNameDirectory
, wxObject
) 
  41 // ---------------------------------------------------------------------------- 
  42 // wxFontRefData - the internal description of the font 
  43 // ---------------------------------------------------------------------------- 
  45 class WXDLLEXPORT wxFontRefData
: public wxGDIRefData
 
  47 friend class WXDLLEXPORT wxFont
; 
  52         Init(12, wxDEFAULT
, wxNORMAL
, wxNORMAL
, FALSE
, 
  53              "", wxFONTENCODING_DEFAULT
); 
  56     wxFontRefData(const wxFontRefData
& data
) 
  58         Init(data
.m_nPointSize
, data
.m_nFamily
, data
.m_nStyle
, data
.m_nWeight
, 
  59              data
.m_bUnderlined
, data
.m_sFaceName
, data
.m_vEncoding
); 
  61         m_nFontId 
= data
.m_nFontId
; 
  64     wxFontRefData( int             nSize
 
  69                   ,const wxString
& sFaceName
 
  70                   ,wxFontEncoding  vEncoding
 
  73         Init(nSize
, nFamily
, nStyle
, nWeight
, bUnderlined
, sFaceName
, vEncoding
); 
  76     virtual ~wxFontRefData(); 
  79     // common part of all ctors 
  85               ,const wxString
& rsFaceName
 
  86               ,wxFontEncoding  vEncoding
 
  90     // If TRUE, the pointer to the actual font is temporary and SHOULD NOT BE 
  91     // DELETED by destructor 
  97     // Font characterstics 
 104     wxString                        m_sFaceName
; 
 105     wxFontEncoding                  m_vEncoding
; 
 108     // Some PM specific stuff 
 111     PFONTMETRICS                    m_pFM
;       // array of FONTMETRICS structs 
 112     int                             m_nNumFonts
; // number of fonts in array 
 113     HPS                             m_hPS
;       // PS handle this font belongs to 
 114     FATTRS                          m_vFattrs
;   // Current fattrs struct 
 115     FACENAMEDESC                    m_vFname
;    // Current facename struct 
 116 }; // end of CLASS wxFontRefData 
 118 // ============================================================================ 
 120 // ============================================================================ 
 122 // ---------------------------------------------------------------------------- 
 124 // ---------------------------------------------------------------------------- 
 126 void wxFontRefData::Init( 
 132 , const wxString
&                   rsFaceName
 
 133 , wxFontEncoding                    vEncoding
 
 137     m_nPointSize  
= nPointSize
; 
 141     m_bUnderlined 
= bUnderlined
; 
 142     m_sFaceName   
= rsFaceName
; 
 143     m_vEncoding   
= vEncoding
; 
 145     m_bTemporary  
= FALSE
; 
 148     m_pFM         
= (PFONTMETRICS
)NULL
; 
 151 } // end of wxFontRefData::Init 
 153 wxFontRefData::~wxFontRefData() 
 157     m_pFM 
= (PFONTMETRICS
)NULL
; 
 160 // ---------------------------------------------------------------------------- 
 162 // ---------------------------------------------------------------------------- 
 167         wxTheFontList
->Append(this); 
 170 // ---------------------------------------------------------------------------- 
 171 // Constructor for a font. Note that the real construction is done 
 172 // in wxDC::SetFont, when information is available about scaling etc. 
 173 // ---------------------------------------------------------------------------- 
 180 , const wxString
&                   rsFaceName
 
 181 , wxFontEncoding                    vEncoding
 
 185     m_refData 
= new wxFontRefData( nPointSize
 
 195 } // end of wxFont::Create 
 200         wxTheFontList
->DeleteObject(this); 
 201 } // end of wxFont::~wxFont 
 203 // ---------------------------------------------------------------------------- 
 204 // real implementation 
 205 // Boris' Kovalenko comments: 
 206 //   Because OS/2 fonts are associated with PS we can not create the font 
 207 //   here, but we may check that font definition is true 
 208 // ---------------------------------------------------------------------------- 
 210 bool wxFont::RealizeResource() 
 214     PFONTMETRICS                    pFM 
= NULL
; 
 217     if ( GetResourceHandle() ) 
 219         // VZ: the old code returned FALSE in this case, but it doesn't seem 
 220         //     to make sense because the font _was_ created 
 221         wxLogDebug(wxT("Calling wxFont::RealizeResource() twice")); 
 227     bool                            bInternalPS 
= FALSE
;  // if we have to create one 
 233     if (!M_FONTDATA
->m_hPS
) 
 235         M_FONTDATA
->m_hPS 
= ::WinGetPS(HWND_DESKTOP
); 
 239     if (M_FONTDATA
->m_pFM
) 
 241         delete [] M_FONTDATA
->m_pFM
; 
 242         M_FONTDATA
->m_pFM 
= NULL
; 
 245     // Determine the number of fonts. 
 247     lNumFonts 
= ::GpiQueryFonts( M_FONTDATA
->m_hPS
 
 251                                 ,(LONG
) sizeof(FONTMETRICS
) 
 256     // Allocate space for the font metrics. 
 258     pFM 
= new FONTMETRICS
[lNumFonts 
+ 1]; 
 261     // Retrieve the font metrics. 
 264     lTemp 
= ::GpiQueryFonts( M_FONTDATA
->m_hPS
 
 268                             ,(LONG
) sizeof(FONTMETRICS
) 
 277     for (int i 
= 0; i 
< lNumFonts
; i
++) 
 279          sVals 
<< "Face: " <<M_FONTDATA
->m_pFM
[i
].szFacename
 
 280                << "Family: " <<M_FONTDATA
->m_pFM
[i
].szFamilyname
 
 281                << " PointSize: " << M_FONTDATA
->m_pFM
[i
].lEmHeight
 
 282                << " Height: " << M_FONTDATA
->m_pFM
[i
].lXHeight
 
 286     M_FONTDATA
->m_vFattrs
.usRecordLength 
= sizeof(FATTRS
); 
 287     M_FONTDATA
->m_vFattrs
.fsFontUse 
= FATTR_FONTUSE_OUTLINE 
|       // only outline fonts allowed 
 288                                       FATTR_FONTUSE_TRANSFORMABLE
;  // may be transformed 
 289     M_FONTDATA
->m_vFattrs
.fsType 
= 0; 
 290     M_FONTDATA
->m_vFattrs
.lMaxBaselineExt 
= M_FONTDATA
->m_vFattrs
.lAveCharWidth 
= 0; 
 291     M_FONTDATA
->m_vFattrs
.idRegistry 
= 0; 
 292     M_FONTDATA
->m_vFattrs
.lMatch 
= 0; 
 294     M_FONTDATA
->m_vFname
.usSize 
= sizeof(FACENAMEDESC
); 
 295     M_FONTDATA
->m_vFname
.usWidthClass 
= FWIDTH_NORMAL
; 
 296     M_FONTDATA
->m_vFname
.usReserved 
= 0; 
 297     M_FONTDATA
->m_vFname
.flOptions 
= 0; 
 299     OS2SelectMatchingFontByName(); 
 301     long                            lNumLids 
= ::GpiQueryNumberSetIds(M_FONTDATA
->m_hPS
); 
 305     // First we should generate unique id 
 313         if(!::GpiQuerySetIds( M_FONTDATA
->m_hPS
 
 321                 ::WinReleasePS(M_FONTDATA
->m_hPS
); 
 325         for(unsigned long LCNum 
= 0; LCNum 
< lNumLids
; LCNum
++) 
 326             if(alIds
[LCNum
] == flId
) 
 328         if(flId 
> 254)  // wow, no id available! 
 331                ::WinReleasePS(M_FONTDATA
->m_hPS
); 
 337     // Release and delete the current font 
 339     ::GpiSetCharSet(M_FONTDATA
->m_hPS
, LCID_DEFAULT
);/* release the font before deleting */ 
 340     ::GpiDeleteSetId(M_FONTDATA
->m_hPS
, 1L);         /* delete the logical font          */ 
 343     // Now build a facestring 
 346     strcpy(zFacename
, M_FONTDATA
->m_vFattrs
.szFacename
); 
 348     if(::GpiQueryFaceString( M_FONTDATA
->m_hPS
 
 350                             ,&M_FONTDATA
->m_vFname
 
 352                             ,M_FONTDATA
->m_vFattrs
.szFacename
 
 355         vError 
= ::WinGetLastError(vHabmain
); 
 358     strcpy(zFacename
, M_FONTDATA
->m_vFattrs
.szFacename
); 
 360     if(::GpiCreateLogFont( M_FONTDATA
->m_hPS
 
 363                           ,&M_FONTDATA
->m_vFattrs
 
 365        M_FONTDATA
->m_hFont 
= (WXHFONT
)1; 
 370         if(M_FONTDATA
->m_hFont
) 
 371             ::GpiDeleteSetId( M_FONTDATA
->m_hPS
 
 375         ::WinReleasePS(M_FONTDATA
->m_hPS
); 
 378         ::GpiSetCharSet(M_FONTDATA
->m_hPS
, flId
); // sets font for presentation space 
 379     if (!M_FONTDATA
->m_hFont
) 
 381         wxLogLastError("CreateFont"); 
 383     M_FONTDATA
->m_nFontId 
= flId
; 
 384     return(M_FONTDATA
->m_hFont 
!= 0); 
 385 } // end of wxFont::RealizeResource 
 387 bool wxFont::FreeResource( 
 391     if (GetResourceHandle()) 
 393         M_FONTDATA
->m_hFont 
= 0; 
 394         ::GpiDeleteSetId( M_FONTDATA
->m_hPS
 
 395                          ,M_FONTDATA
->m_nFontId
 
 400 } // end of wxFont::FreeResource 
 402 WXHANDLE 
wxFont::GetHFONT() const 
 407         return (WXHANDLE
)M_FONTDATA
->m_hFont
; 
 408 } // end of wxFont::GetHFONT 
 410 WXHANDLE 
wxFont::GetResourceHandle() 
 413 } // end of wxFont::GetResourceHandle 
 415 bool wxFont::IsFree() const 
 417     return (M_FONTDATA 
&& (M_FONTDATA
->m_hFont 
== 0)); 
 418 } // end of wxFont::IsFree 
 420 void wxFont::Unshare() 
 422     // Don't change shared data 
 425         m_refData 
= new wxFontRefData(); 
 429         wxFontRefData
* ref 
= new wxFontRefData(*M_FONTDATA
); 
 433 } // end of wxFont::Unshare 
 435 // ---------------------------------------------------------------------------- 
 436 // change font attribute: we recreate font when doing it 
 437 // ---------------------------------------------------------------------------- 
 439 void wxFont::SetPointSize( 
 445     M_FONTDATA
->m_nPointSize 
= nPointSize
; 
 448 } // end of wxFont::SetPointSize 
 450 void wxFont::SetFamily( 
 456     M_FONTDATA
->m_nFamily 
= nFamily
; 
 459 } // end of wxFont::SetFamily 
 461 void wxFont::SetStyle( 
 467     M_FONTDATA
->m_nStyle 
= nStyle
; 
 470 } // end of wxFont::SetStyle 
 472 void wxFont::SetWeight( 
 478     M_FONTDATA
->m_nWeight 
= nWeight
; 
 481 } // end of wxFont::SetWeight 
 483 void wxFont::SetFaceName( 
 484   const wxString
&                   rsFaceName
 
 489     M_FONTDATA
->m_sFaceName 
= rsFaceName
; 
 492 } // end of wxFont::SetFaceName 
 494 void wxFont::SetUnderlined( 
 500     M_FONTDATA
->m_bUnderlined 
= bUnderlined
; 
 503 } // end of wxFont::SetUnderlined 
 505 void wxFont::SetEncoding( 
 506   wxFontEncoding                    vEncoding
 
 511     M_FONTDATA
->m_vEncoding 
= vEncoding
; 
 514 } // end of wxFont::SetEncoding 
 522     M_FONTDATA
->m_hPS 
= hPS
; 
 525 } // end of wxFont::SetPS 
 533     // Don't realize the font with this one 
 535     M_FONTDATA
->m_pFM 
= pFM
; 
 536     M_FONTDATA
->m_nNumFonts 
= nNumFonts
; 
 537 } // end of wxFont::SetFM 
 539 // ---------------------------------------------------------------------------- 
 541 // ---------------------------------------------------------------------------- 
 543 int wxFont::GetPointSize() const 
 549       return pTmp
->m_nPointSize
; 
 552 } // end of wxFont::GetPointSize 
 554 int wxFont::GetFamily() const 
 556     return M_FONTDATA
->m_nFamily
; 
 557 } // end of wxFont::GetFamily 
 559 int wxFont::GetFontId() const 
 561     return M_FONTDATA
->m_nFontId
; 
 562 } // end of wxFont::GetFontId 
 564 int wxFont::GetStyle() const 
 566     return M_FONTDATA
->m_nStyle
; 
 567 } // end of wxFont::GetStyle 
 569 int wxFont::GetWeight() const 
 571     return M_FONTDATA
->m_nWeight
; 
 574 bool wxFont::GetUnderlined() const 
 576     return M_FONTDATA
->m_bUnderlined
; 
 577 } // end of wxFont::GetUnderlined 
 579 wxString 
wxFont::GetFaceName() const 
 584         sStr 
= M_FONTDATA
->m_sFaceName 
; 
 586 } // end of wxFont::GetFaceName 
 588 wxFontEncoding 
wxFont::GetEncoding() const 
 590     return M_FONTDATA
->m_vEncoding
; 
 591 } // end of wxFont::GetEncoding 
 593 HPS 
wxFont::GetPS() const 
 595     return M_FONTDATA
->m_hPS
; 
 596 } // end of wxFont::GetPS 
 598 void wxFont::OS2SelectMatchingFontByName() 
 611     char                            zFontFaceName
[FACESIZE
]; 
 613     USHORT                          usWeightClass
; 
 617     for(i 
= 0;i 
< 16; i
++) 
 618         anMinDiff
[i
] = nMinDiff0
; 
 623             sFaceName 
= wxT("Script"); 
 628             sFaceName 
= wxT("Times New Roman"); 
 633             sFaceName 
= wxT("Courier") ; 
 637             sFaceName 
= wxT("WarpSans") ; 
 642             sFaceName 
= wxT("Helv") ; 
 648             wxFAIL_MSG(_T("unknown font weight")); 
 650             usWeightClass 
= FWEIGHT_DONT_CARE
; 
 654             usWeightClass 
= FWEIGHT_NORMAL
; 
 658             usWeightClass 
= FWEIGHT_LIGHT
; 
 662             usWeightClass 
= FWEIGHT_BOLD
; 
 665          case wxFONTWEIGHT_MAX
: 
 666             usWeightClass 
= FWEIGHT_ULTRA_BOLD
; 
 669     M_FONTDATA
->m_vFname
.usWeightClass 
= usWeightClass
; 
 675             fsSelection 
= FM_SEL_ITALIC
; 
 676             M_FONTDATA
->m_vFname
.flOptions 
= FTYPE_ITALIC
; 
 680             wxFAIL_MSG(wxT("unknown font slant")); 
 688     wxStrncpy(zFontFaceName
, sFaceName
.c_str(), WXSIZEOF(zFontFaceName
)); 
 689     M_FONTDATA
->m_nPointSize 
= GetPointSize(); 
 691     for(i 
= 0, nIs 
= 0; i 
< M_FONTDATA
->m_nNumFonts
; i
++) 
 694         int nPointSize 
= M_FONTDATA
->m_nPointSize
; 
 697         anDiff
[0] = wxGpiStrcmp(M_FONTDATA
->m_pFM
[i
].szFamilyname
, zFontFaceName
); 
 698         anDiff
[1] = abs(M_FONTDATA
->m_pFM
[i
].lEmHeight 
- M_FONTDATA
->m_nPointSize
); 
 699         anDiff
[2] = abs(M_FONTDATA
->m_pFM
[i
].usWeightClass 
-  usWeightClass
); 
 700         anDiff
[3] = abs((M_FONTDATA
->m_pFM
[i
].fsSelection 
& 0x2f) -  fsSelection
); 
 703             nEmHeight 
= (int)M_FONTDATA
->m_pFM
[i
].lEmHeight
; 
 704             nXHeight  
=(int)M_FONTDATA
->m_pFM
[i
].lXHeight
; 
 705             if( (nIs 
& 0x01) == 0) 
 709                 anMinDiff
[1] = anDiff
[1]; 
 710                 anMinDiff
[2] = anDiff
[2]; 
 711                 anMinDiff
[3] = anDiff
[3]; 
 713             else if(anDiff
[3] < anMinDiff
[3]) 
 716                 anMinDiff
[3] = anDiff
[3]; 
 718             else if(anDiff
[2] < anMinDiff
[2]) 
 721                 anMinDiff
[2] = anDiff
[2]; 
 723             else if(anDiff
[1] < anMinDiff
[1]) 
 726                 anMinDiff
[1] = anDiff
[1]; 
 730         else if(anDiff
[0] < anMinDiff
[0]) 
 734               anMinDiff
[3] = anDiff
[3]; 
 735               anMinDiff
[2] = anDiff
[2]; 
 736               anMinDiff
[1] = anDiff
[1]; 
 737               anMinDiff
[0] = anDiff
[0]; 
 739         else if(anDiff
[0] == anMinDiff
[0]) 
 741             if(anDiff
[3] < anMinDiff
[3]) 
 744                 anMinDiff
[3] = anDiff
[3]; 
 747             else if(anDiff
[2] < anMinDiff
[2]) 
 750                 anMinDiff
[2] = anDiff
[2]; 
 753             else if(anDiff
[1] < anMinDiff
[1]) 
 756                 anMinDiff
[1] = anDiff
[1]; 
 762     M_FONTDATA
->m_vFattrs
.usRecordLength 
= sizeof(FATTRS
);                        // sets size of structure 
 763     M_FONTDATA
->m_vFattrs
.fsSelection    
= M_FONTDATA
->m_pFM
[nIndex
].fsSelection
; // uses default selection 
 764     M_FONTDATA
->m_vFattrs
.lMatch         
= M_FONTDATA
->m_pFM
[nIndex
].lMatch
;      // force match 
 765     M_FONTDATA
->m_vFattrs
.idRegistry     
= M_FONTDATA
->m_pFM
[nIndex
].idRegistry
;  // uses default registry 
 766     M_FONTDATA
->m_vFattrs
.usCodePage     
= M_FONTDATA
->m_pFM
[nIndex
].usCodePage
;  // code-page 
 767     if(M_FONTDATA
->m_pFM
[nIndex
].lMatch
) 
 769         M_FONTDATA
->m_vFattrs
.lMaxBaselineExt 
= M_FONTDATA
->m_pFM
[nIndex
].lMaxBaselineExt
; // requested font height 
 770         M_FONTDATA
->m_vFattrs
.lAveCharWidth   
= M_FONTDATA
->m_pFM
[nIndex
].lAveCharWidth 
;  // requested font width 
 774         M_FONTDATA
->m_vFattrs
.lMaxBaselineExt 
= 0; 
 775         M_FONTDATA
->m_vFattrs
.lAveCharWidth   
= 0; 
 777     M_FONTDATA
->m_vFattrs
.fsType    
= 0;// pfm->fsType;              /* uses default type       */ 
 778     M_FONTDATA
->m_vFattrs
.fsFontUse 
= 0; 
 780     wxStrcpy(M_FONTDATA
->m_vFattrs
.szFacename
, M_FONTDATA
->m_pFM
[nIndex
].szFacename
); 
 782     strcpy(zFontFaceName
, M_FONTDATA
->m_pFM
[nIndex
].szFacename
); 
 783     strcpy(zFontFaceName
, M_FONTDATA
->m_vFattrs
.szFacename
); 
 785     if(usWeightClass 
>= FWEIGHT_BOLD
) 
 786         M_FONTDATA
->m_vFattrs
.fsSelection 
|= FATTR_SEL_BOLD
; 
 788         M_FONTDATA
->m_vFattrs
.fsSelection 
|= FATTR_SEL_UNDERSCORE
; 
 789     if(fsSelection 
& FM_SEL_ITALIC
) 
 790         M_FONTDATA
->m_vFattrs
.fsSelection 
|= FATTR_SEL_ITALIC
;