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
;