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::GetResourceHandle()
407 return (WXHANDLE
)M_FONTDATA
->m_hFont
;
408 } // end of wxFont::GetResourceHandle
410 bool wxFont::IsFree() const
412 return (M_FONTDATA
&& (M_FONTDATA
->m_hFont
== 0));
413 } // end of wxFont::IsFree
415 void wxFont::Unshare()
417 // Don't change shared data
420 m_refData
= new wxFontRefData();
424 wxFontRefData
* ref
= new wxFontRefData(*M_FONTDATA
);
428 } // end of wxFont::Unshare
430 // ----------------------------------------------------------------------------
431 // change font attribute: we recreate font when doing it
432 // ----------------------------------------------------------------------------
434 void wxFont::SetPointSize(
440 M_FONTDATA
->m_nPointSize
= nPointSize
;
443 } // end of wxFont::SetPointSize
445 void wxFont::SetFamily(
451 M_FONTDATA
->m_nFamily
= nFamily
;
454 } // end of wxFont::SetFamily
456 void wxFont::SetStyle(
462 M_FONTDATA
->m_nStyle
= nStyle
;
465 } // end of wxFont::SetStyle
467 void wxFont::SetWeight(
473 M_FONTDATA
->m_nWeight
= nWeight
;
476 } // end of wxFont::SetWeight
478 void wxFont::SetFaceName(
479 const wxString
& rsFaceName
484 M_FONTDATA
->m_sFaceName
= rsFaceName
;
487 } // end of wxFont::SetFaceName
489 void wxFont::SetUnderlined(
495 M_FONTDATA
->m_bUnderlined
= bUnderlined
;
498 } // end of wxFont::SetUnderlined
500 void wxFont::SetEncoding(
501 wxFontEncoding vEncoding
506 M_FONTDATA
->m_vEncoding
= vEncoding
;
509 } // end of wxFont::SetEncoding
517 M_FONTDATA
->m_hPS
= hPS
;
520 } // end of wxFont::SetPS
528 // Don't realize the font with this one
530 M_FONTDATA
->m_pFM
= pFM
;
531 M_FONTDATA
->m_nNumFonts
= nNumFonts
;
532 } // end of wxFont::SetFM
534 // ----------------------------------------------------------------------------
536 // ----------------------------------------------------------------------------
538 int wxFont::GetPointSize() const
544 return pTmp
->m_nPointSize
;
547 } // end of wxFont::GetPointSize
549 int wxFont::GetFamily() const
551 return M_FONTDATA
->m_nFamily
;
552 } // end of wxFont::GetFamily
554 int wxFont::GetFontId() const
556 return M_FONTDATA
->m_nFontId
;
557 } // end of wxFont::GetFontId
559 int wxFont::GetStyle() const
561 return M_FONTDATA
->m_nStyle
;
562 } // end of wxFont::GetStyle
564 int wxFont::GetWeight() const
566 return M_FONTDATA
->m_nWeight
;
569 bool wxFont::GetUnderlined() const
571 return M_FONTDATA
->m_bUnderlined
;
572 } // end of wxFont::GetUnderlined
574 wxString
wxFont::GetFaceName() const
579 sStr
= M_FONTDATA
->m_sFaceName
;
581 } // end of wxFont::GetFaceName
583 wxFontEncoding
wxFont::GetEncoding() const
585 return M_FONTDATA
->m_vEncoding
;
586 } // end of wxFont::GetEncoding
588 HPS
wxFont::GetPS() const
590 return M_FONTDATA
->m_hPS
;
591 } // end of wxFont::GetPS
593 void wxFont::OS2SelectMatchingFontByName()
606 char zFontFaceName
[FACESIZE
];
608 USHORT usWeightClass
;
612 for(i
= 0;i
< 16; i
++)
613 anMinDiff
[i
] = nMinDiff0
;
618 sFaceName
= wxT("Script");
623 sFaceName
= wxT("Times New Roman");
628 sFaceName
= wxT("Courier") ;
632 sFaceName
= wxT("WarpSans") ;
637 sFaceName
= wxT("Helv") ;
643 wxFAIL_MSG(_T("unknown font weight"));
645 usWeightClass
= FWEIGHT_DONT_CARE
;
649 usWeightClass
= FWEIGHT_NORMAL
;
653 usWeightClass
= FWEIGHT_LIGHT
;
657 usWeightClass
= FWEIGHT_BOLD
;
660 case wxFONTWEIGHT_MAX
:
661 usWeightClass
= FWEIGHT_ULTRA_BOLD
;
664 M_FONTDATA
->m_vFname
.usWeightClass
= usWeightClass
;
670 fsSelection
= FM_SEL_ITALIC
;
671 M_FONTDATA
->m_vFname
.flOptions
= FTYPE_ITALIC
;
675 wxFAIL_MSG(wxT("unknown font slant"));
683 wxStrncpy(zFontFaceName
, sFaceName
.c_str(), WXSIZEOF(zFontFaceName
));
684 M_FONTDATA
->m_nPointSize
= GetPointSize();
686 for(i
= 0, nIs
= 0; i
< M_FONTDATA
->m_nNumFonts
; i
++)
689 int nPointSize
= M_FONTDATA
->m_nPointSize
;
692 anDiff
[0] = wxGpiStrcmp(M_FONTDATA
->m_pFM
[i
].szFamilyname
, zFontFaceName
);
693 anDiff
[1] = abs(M_FONTDATA
->m_pFM
[i
].lEmHeight
- M_FONTDATA
->m_nPointSize
);
694 anDiff
[2] = abs(M_FONTDATA
->m_pFM
[i
].usWeightClass
- usWeightClass
);
695 anDiff
[3] = abs((M_FONTDATA
->m_pFM
[i
].fsSelection
& 0x2f) - fsSelection
);
698 nEmHeight
= (int)M_FONTDATA
->m_pFM
[i
].lEmHeight
;
699 nXHeight
=(int)M_FONTDATA
->m_pFM
[i
].lXHeight
;
700 if( (nIs
& 0x01) == 0)
704 anMinDiff
[1] = anDiff
[1];
705 anMinDiff
[2] = anDiff
[2];
706 anMinDiff
[3] = anDiff
[3];
708 else if(anDiff
[3] < anMinDiff
[3])
711 anMinDiff
[3] = anDiff
[3];
713 else if(anDiff
[2] < anMinDiff
[2])
716 anMinDiff
[2] = anDiff
[2];
718 else if(anDiff
[1] < anMinDiff
[1])
721 anMinDiff
[1] = anDiff
[1];
725 else if(anDiff
[0] < anMinDiff
[0])
729 anMinDiff
[3] = anDiff
[3];
730 anMinDiff
[2] = anDiff
[2];
731 anMinDiff
[1] = anDiff
[1];
732 anMinDiff
[0] = anDiff
[0];
734 else if(anDiff
[0] == anMinDiff
[0])
736 if(anDiff
[3] < anMinDiff
[3])
739 anMinDiff
[3] = anDiff
[3];
742 else if(anDiff
[2] < anMinDiff
[2])
745 anMinDiff
[2] = anDiff
[2];
748 else if(anDiff
[1] < anMinDiff
[1])
751 anMinDiff
[1] = anDiff
[1];
757 M_FONTDATA
->m_vFattrs
.usRecordLength
= sizeof(FATTRS
); // sets size of structure
758 M_FONTDATA
->m_vFattrs
.fsSelection
= M_FONTDATA
->m_pFM
[nIndex
].fsSelection
; // uses default selection
759 M_FONTDATA
->m_vFattrs
.lMatch
= M_FONTDATA
->m_pFM
[nIndex
].lMatch
; // force match
760 M_FONTDATA
->m_vFattrs
.idRegistry
= M_FONTDATA
->m_pFM
[nIndex
].idRegistry
; // uses default registry
761 M_FONTDATA
->m_vFattrs
.usCodePage
= M_FONTDATA
->m_pFM
[nIndex
].usCodePage
; // code-page
762 if(M_FONTDATA
->m_pFM
[nIndex
].lMatch
)
764 M_FONTDATA
->m_vFattrs
.lMaxBaselineExt
= M_FONTDATA
->m_pFM
[nIndex
].lMaxBaselineExt
; // requested font height
765 M_FONTDATA
->m_vFattrs
.lAveCharWidth
= M_FONTDATA
->m_pFM
[nIndex
].lAveCharWidth
; // requested font width
769 M_FONTDATA
->m_vFattrs
.lMaxBaselineExt
= 0;
770 M_FONTDATA
->m_vFattrs
.lAveCharWidth
= 0;
772 M_FONTDATA
->m_vFattrs
.fsType
= 0;// pfm->fsType; /* uses default type */
773 M_FONTDATA
->m_vFattrs
.fsFontUse
= 0;
775 wxStrcpy(M_FONTDATA
->m_vFattrs
.szFacename
, M_FONTDATA
->m_pFM
[nIndex
].szFacename
);
777 strcpy(zFontFaceName
, M_FONTDATA
->m_pFM
[nIndex
].szFacename
);
778 strcpy(zFontFaceName
, M_FONTDATA
->m_vFattrs
.szFacename
);
780 if(usWeightClass
>= FWEIGHT_BOLD
)
781 M_FONTDATA
->m_vFattrs
.fsSelection
|= FATTR_SEL_BOLD
;
783 M_FONTDATA
->m_vFattrs
.fsSelection
|= FATTR_SEL_UNDERSCORE
;
784 if(fsSelection
& FM_SEL_ITALIC
)
785 M_FONTDATA
->m_vFattrs
.fsSelection
|= FATTR_SEL_ITALIC
;