From 4580cdb9adbbfd32d5e9f4a7e845df17714d5557 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Sat, 1 Sep 2018 19:42:18 +0200 Subject: [PATCH] Extending wxFont API & OSX Core Text Implementation (#877) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Switch to pure Core Text Implementation, Start extended Font API * mac fixes * First msw implementation * Fixing paste error * fixing typo * Rearranging lines to former fallthrough order * Blind fixes for covering new abstract methods * Blind gtk implementations * Fixing according to travis .. * Removing method defined in base * formatting adaptions * Extending the schema definition for new weights * fixing typo, using wxRound, other fixes according to comments * changes according to suggestions * fixing init order, before the init of m_info was overridden by Init() * redo * redo * redo * Cleanup Removing obsolete code snippets, proper traces for font names * Moving common code Only the Get/SetNumericWeight calls should now be implemented in the native part, the ‚old‘ Get/SetWeight are common code and use the numeric counterparts. * Updating docs * commit wa missing changes.txt * Doc fixes * Full stops added --- docs/changes.txt | 4 +- include/wx/font.h | 23 +- include/wx/fontutil.h | 66 +- include/wx/gtk/font.h | 6 +- include/wx/msw/font.h | 6 +- include/wx/osx/core/cfdictionary.h | 14 +- include/wx/osx/font.h | 67 +- interface/wx/font.h | 75 +- interface/wx/fontutil.h | 7 +- misc/schema/xrc_schema.rnc | 4 +- src/common/dcsvg.cpp | 22 +- src/common/fontcmn.cpp | 165 +++- src/gtk/font.cpp | 33 +- src/msw/font.cpp | 76 +- src/osx/carbon/font.cpp | 1206 ++++++++++++++++------------ src/osx/carbon/fontdlgosx.mm | 46 +- src/osx/carbon/graphics.cpp | 11 +- src/osx/carbon/utilscocoa.mm | 44 - src/propgrid/advprops.cpp | 24 +- src/qt/font.cpp | 18 +- src/unix/fontutil.cpp | 75 +- src/xrc/xmlres.cpp | 18 +- 22 files changed, 1210 insertions(+), 800 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index d40be39dc9..1f598bf161 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -155,7 +155,7 @@ INCOMPATIBLE CHANGES SINCE 3.1.0: - The enum value wxTASKBAR_JUMP_LIST_DESTIONATION, which was added in 3.1.0, contains a typo and has been renamed to wxTASKBAR_JUMP_LIST_DESTINATION. - + - wxZipOutputStream will now automatically convert filenames to UTF-8, if the wxMBConv used when calling the constructor supports UTF-8 encoding. @@ -489,6 +489,8 @@ All (GUI): - Allow suppressing warnings from wxImage::LoadFile(). - Allow customizing wxRibbon highlight colours (wxBen). - Enable selecting opacity in generic wxColourPicker. +- Extend the support for font weights to a bigger range. +- Add support for fractional font sizes. wxGTK: diff --git a/include/wx/font.h b/include/wx/font.h index e1a07a2e01..249859fc16 100644 --- a/include/wx/font.h +++ b/include/wx/font.h @@ -59,10 +59,18 @@ enum wxFontStyle // font weights enum wxFontWeight { - wxFONTWEIGHT_NORMAL = wxNORMAL, - wxFONTWEIGHT_LIGHT = wxLIGHT, - wxFONTWEIGHT_BOLD = wxBOLD, - wxFONTWEIGHT_MAX + wxFONTWEIGHT_INVALID = 0, + wxFONTWEIGHT_THIN = 100, + wxFONTWEIGHT_EXTRALIGHT = 200, + wxFONTWEIGHT_LIGHT = 300, + wxFONTWEIGHT_NORMAL = 400, + wxFONTWEIGHT_MEDIUM = 500, + wxFONTWEIGHT_SEMIBOLD = 600, + wxFONTWEIGHT_BOLD = 700, + wxFONTWEIGHT_EXTRABOLD = 800, + wxFONTWEIGHT_HEAVY = 900, + wxFONTWEIGHT_EXTRAHEAVY = 1000, + wxFONTWEIGHT_MAX = wxFONTWEIGHT_EXTRAHEAVY }; // Symbolic font sizes as defined in CSS specification. @@ -338,12 +346,14 @@ public: bool operator!=(const wxFont& font) const { return !(*this == font); } // accessors: get the font characteristics - virtual int GetPointSize() const = 0; + virtual int GetPointSize() const; + virtual float GetFractionalPointSize() const = 0; virtual wxSize GetPixelSize() const; virtual bool IsUsingSizeInPixels() const; wxFontFamily GetFamily() const; virtual wxFontStyle GetStyle() const = 0; virtual wxFontWeight GetWeight() const = 0; + virtual int GetNumericWeight() const = 0; virtual bool GetUnderlined() const = 0; virtual bool GetStrikethrough() const { return false; } virtual wxString GetFaceName() const = 0; @@ -356,11 +366,12 @@ public: wxString GetNativeFontInfoUserDesc() const; // change the font characteristics - virtual void SetPointSize( int pointSize ) = 0; + virtual void SetPointSize( float pointSize ) = 0; virtual void SetPixelSize( const wxSize& pixelSize ); virtual void SetFamily( wxFontFamily family ) = 0; virtual void SetStyle( wxFontStyle style ) = 0; virtual void SetWeight( wxFontWeight weight ) = 0; + virtual void SetNumericWeight( int weight ) = 0; virtual void SetUnderlined( bool underlined ) = 0; virtual void SetStrikethrough( bool WXUNUSED(strikethrough) ) {} diff --git a/include/wx/fontutil.h b/include/wx/fontutil.h index ccdda1d76f..df9c8262cc 100644 --- a/include/wx/fontutil.h +++ b/include/wx/fontutil.h @@ -29,6 +29,10 @@ #include #endif +#if defined(__WXOSX__) +#include "wx/osx/core/cfref.h" +#endif + class WXDLLIMPEXP_FWD_BASE wxArrayString; struct WXDLLIMPEXP_FWD_CORE wxNativeEncodingInfo; @@ -120,20 +124,7 @@ public: #elif defined(__WXOSX__) public: wxNativeFontInfo(const wxNativeFontInfo& info) { Init(info); } - wxNativeFontInfo( int size, - wxFontFamily family, - wxFontStyle style, - wxFontWeight weight, - bool underlined, - bool strikethrough, - const wxString& faceName, - wxFontEncoding encoding) - { - Init(size, family, style, weight, - underlined, strikethrough, - faceName, encoding); - } - + ~wxNativeFontInfo() { Free(); } wxNativeFontInfo& operator=(const wxNativeFontInfo& info) @@ -146,30 +137,44 @@ public: return *this; } - void Init(CTFontDescriptorRef descr); + void InitFromFont(CTFontRef font); + void InitFromFontDescriptor(CTFontDescriptorRef font); void Init(const wxNativeFontInfo& info); - void Init(int size, - wxFontFamily family, - wxFontStyle style, - wxFontWeight weight, - bool underlined, - bool strikethrough, - const wxString& faceName , - wxFontEncoding encoding); void Free(); + wxString GetFamilyName() const; + wxString GetStyleName() const; + static void UpdateNamesMap(const wxString& familyname, CTFontDescriptorRef descr); static void UpdateNamesMap(const wxString& familyname, CTFontRef font); - int m_pointSize; - wxFontFamily m_family; + static CGFloat GetCTWeight( CTFontRef font ); + static CGFloat GetCTWeight( CTFontDescriptorRef font ); + static CGFloat GetCTSlant( CTFontDescriptorRef font ); + + + CTFontDescriptorRef GetCTFontDescriptor() const; +private: + // attributes for regenerating a CTFontDescriptor, stay close to native values + // for better roundtrip fidelity + CGFloat m_ctWeight; wxFontStyle m_style; - wxFontWeight m_weight; + CGFloat m_ctSize; + wxFontFamily m_family; + + wxString m_styleName; + wxString m_familyName; + + // native font description + wxCFRef m_descriptor; + void CreateCTFontDescriptor(); + + // these attributes are not part of a CTFont bool m_underlined; bool m_strikethrough; - wxString m_faceName; wxFontEncoding m_encoding; + public : #elif defined(__WXQT__) QFont m_qtFont; @@ -219,7 +224,7 @@ public: // init with the parameters of the given font void InitFromFont(const wxFont& font) { -#if wxUSE_PANGO +#if wxUSE_PANGO || defined(__WXOSX__) Init(*font.GetNativeFontInfo()); #else // translate all font parameters @@ -252,18 +257,21 @@ public: // accessors and modifiers for the font elements int GetPointSize() const; + float GetFractionalPointSize() const; wxSize GetPixelSize() const; wxFontStyle GetStyle() const; wxFontWeight GetWeight() const; + int GetNumericWeight() const; bool GetUnderlined() const; bool GetStrikethrough() const; wxString GetFaceName() const; wxFontFamily GetFamily() const; wxFontEncoding GetEncoding() const; - void SetPointSize(int pointsize); + void SetPointSize(float pointsize); void SetPixelSize(const wxSize& pixelSize); void SetStyle(wxFontStyle style); + void SetNumericWeight(int weight); void SetWeight(wxFontWeight weight); void SetUnderlined(bool underlined); void SetStrikethrough(bool strikethrough); diff --git a/include/wx/gtk/font.h b/include/wx/gtk/font.h index 4d1220617d..20359e319b 100644 --- a/include/wx/gtk/font.h +++ b/include/wx/gtk/font.h @@ -64,9 +64,10 @@ public: virtual ~wxFont(); // implement base class pure virtuals - virtual int GetPointSize() const wxOVERRIDE; + virtual float GetFractionalPointSize() const wxOVERRIDE; virtual wxFontStyle GetStyle() const wxOVERRIDE; virtual wxFontWeight GetWeight() const wxOVERRIDE; + virtual int GetNumericWeight() const wxOVERRIDE; virtual wxString GetFaceName() const wxOVERRIDE; virtual bool GetUnderlined() const wxOVERRIDE; virtual bool GetStrikethrough() const wxOVERRIDE; @@ -74,10 +75,11 @@ public: virtual const wxNativeFontInfo *GetNativeFontInfo() const wxOVERRIDE; virtual bool IsFixedWidth() const wxOVERRIDE; - virtual void SetPointSize( int pointSize ) wxOVERRIDE; + virtual void SetPointSize(float pointSize) wxOVERRIDE; virtual void SetFamily(wxFontFamily family) wxOVERRIDE; virtual void SetStyle(wxFontStyle style) wxOVERRIDE; virtual void SetWeight(wxFontWeight weight) wxOVERRIDE; + virtual void SetNumericWeight(int weight) wxOVERRIDE; virtual bool SetFaceName( const wxString& faceName ) wxOVERRIDE; virtual void SetUnderlined( bool underlined ) wxOVERRIDE; virtual void SetStrikethrough(bool strikethrough) wxOVERRIDE; diff --git a/include/wx/msw/font.h b/include/wx/msw/font.h index eec24baedb..2e4fade8f2 100644 --- a/include/wx/msw/font.h +++ b/include/wx/msw/font.h @@ -85,22 +85,24 @@ public: virtual ~wxFont(); // implement base class pure virtuals - virtual int GetPointSize() const wxOVERRIDE; + virtual float GetFractionalPointSize() const wxOVERRIDE; virtual wxSize GetPixelSize() const wxOVERRIDE; virtual bool IsUsingSizeInPixels() const wxOVERRIDE; virtual wxFontStyle GetStyle() const wxOVERRIDE; virtual wxFontWeight GetWeight() const wxOVERRIDE; + virtual int GetNumericWeight() const wxOVERRIDE; virtual bool GetUnderlined() const wxOVERRIDE; virtual bool GetStrikethrough() const wxOVERRIDE; virtual wxString GetFaceName() const wxOVERRIDE; virtual wxFontEncoding GetEncoding() const wxOVERRIDE; virtual const wxNativeFontInfo *GetNativeFontInfo() const wxOVERRIDE; - virtual void SetPointSize(int pointSize) wxOVERRIDE; + virtual void SetPointSize(float pointSize) wxOVERRIDE; virtual void SetPixelSize(const wxSize& pixelSize) wxOVERRIDE; virtual void SetFamily(wxFontFamily family) wxOVERRIDE; virtual void SetStyle(wxFontStyle style) wxOVERRIDE; virtual void SetWeight(wxFontWeight weight) wxOVERRIDE; + virtual void SetNumericWeight(int weight) wxOVERRIDE; virtual bool SetFaceName(const wxString& faceName) wxOVERRIDE; virtual void SetUnderlined(bool underlined) wxOVERRIDE; virtual void SetStrikethrough(bool strikethrough) wxOVERRIDE; diff --git a/include/wx/osx/core/cfdictionary.h b/include/wx/osx/core/cfdictionary.h index 5c2c3b4f93..fddbb52654 100644 --- a/include/wx/osx/core/cfdictionary.h +++ b/include/wx/osx/core/cfdictionary.h @@ -79,12 +79,17 @@ public: { } - explicit wxCFDictionaryRef(CFDictionaryRef r) + wxCFDictionaryRef(CFDictionaryRef r) : wxCFDictionaryRefCommon(r) { } wxCFDictionaryRef& operator=(const wxCFMutableDictionaryRef& other); + + CFDictionaryRef CreateCopy() const + { + return CFDictionaryCreateCopy(kCFAllocatorDefault, this->m_ptr); + } }; class wxCFMutableDictionaryRef : public wxCFDictionaryRefCommon @@ -95,7 +100,7 @@ public: { } - explicit wxCFMutableDictionaryRef(CFMutableDictionaryRef r) + wxCFMutableDictionaryRef(CFMutableDictionaryRef r) : wxCFDictionaryRefCommon(r) { } @@ -109,6 +114,11 @@ public: { SetValue(key, wxCFNumberRef(v)); } + + CFMutableDictionaryRef CreateCopy() const + { + return CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, this->m_ptr); + } friend class wxCFDictionaryRef; }; diff --git a/include/wx/osx/font.h b/include/wx/osx/font.h index fcd82013f5..5078cd32ce 100644 --- a/include/wx/osx/font.h +++ b/include/wx/osx/font.h @@ -51,6 +51,7 @@ public: } wxFont( wxOSXSystemFont systemFont ); + wxFont(CTFontRef font); #if wxOSX_USE_COCOA wxFont(WX_NSFont nsfont); @@ -67,6 +68,17 @@ public: Create(size, family, style, weight, underlined, face, encoding); } + wxFont(float size, + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, + bool underlined = false, + const wxString& face = wxEmptyString, + wxFontEncoding encoding = wxFONTENCODING_DEFAULT) + { + Create(size, family, style, weight, underlined, face, encoding); + } + wxFont(const wxSize& pixelSize, wxFontFamily family, wxFontStyle style, @@ -87,6 +99,14 @@ public: const wxString& face = wxEmptyString, wxFontEncoding encoding = wxFONTENCODING_DEFAULT); + bool Create(float size, + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, + bool underlined = false, + const wxString& face = wxEmptyString, + wxFontEncoding encoding = wxFONTENCODING_DEFAULT); + wxFont(const wxNativeFontInfo& info) { (void)Create(info); @@ -99,26 +119,28 @@ public: virtual ~wxFont(); // implement base class pure virtuals - virtual int GetPointSize() const; - virtual wxSize GetPixelSize() const; - virtual wxFontStyle GetStyle() const; - virtual wxFontWeight GetWeight() const; - virtual bool GetUnderlined() const; - virtual bool GetStrikethrough() const; - virtual wxString GetFaceName() const; - virtual wxFontEncoding GetEncoding() const; - virtual const wxNativeFontInfo *GetNativeFontInfo() const; + virtual float GetFractionalPointSize() const wxOVERRIDE; + virtual wxSize GetPixelSize() const wxOVERRIDE; + virtual wxFontStyle GetStyle() const wxOVERRIDE; + virtual wxFontWeight GetWeight() const wxOVERRIDE; + virtual int GetNumericWeight() const wxOVERRIDE; + virtual bool GetUnderlined() const wxOVERRIDE; + virtual bool GetStrikethrough() const wxOVERRIDE; + virtual wxString GetFaceName() const wxOVERRIDE; + virtual wxFontEncoding GetEncoding() const wxOVERRIDE; + virtual const wxNativeFontInfo *GetNativeFontInfo() const wxOVERRIDE; - virtual bool IsFixedWidth() const; + virtual bool IsFixedWidth() const wxOVERRIDE; - virtual void SetPointSize(int pointSize); - virtual void SetFamily(wxFontFamily family); - virtual void SetStyle(wxFontStyle style); - virtual void SetWeight(wxFontWeight weight); - virtual bool SetFaceName(const wxString& faceName); - virtual void SetUnderlined(bool underlined); - virtual void SetStrikethrough(bool strikethrough); - virtual void SetEncoding(wxFontEncoding encoding); + virtual void SetPointSize(float pointSize) wxOVERRIDE; + virtual void SetFamily(wxFontFamily family) wxOVERRIDE; + virtual void SetStyle(wxFontStyle style) wxOVERRIDE; + virtual void SetWeight(wxFontWeight weight) wxOVERRIDE; + virtual void SetNumericWeight(int weight) wxOVERRIDE; + virtual bool SetFaceName(const wxString& faceName) wxOVERRIDE; + virtual void SetUnderlined(bool underlined) wxOVERRIDE; + virtual void SetStrikethrough(bool strikethrough) wxOVERRIDE; + virtual void SetEncoding(wxFontEncoding encoding) wxOVERRIDE; wxDECLARE_COMMON_FONT_METHODS(); @@ -148,7 +170,6 @@ public: #if wxOSX_USE_COCOA WX_NSFont OSXGetNSFont() const; - static void SetNativeInfoFromNSFont(WX_NSFont nsfont, wxNativeFontInfo* info); #endif #if wxOSX_USE_IPHONE @@ -156,11 +177,11 @@ public: #endif protected: - virtual void DoSetNativeFontInfo(const wxNativeFontInfo& info); - virtual wxFontFamily DoGetFamily() const; + virtual void DoSetNativeFontInfo(const wxNativeFontInfo& info) wxOVERRIDE; + virtual wxFontFamily DoGetFamily() const wxOVERRIDE; - virtual wxGDIRefData *CreateGDIRefData() const; - virtual wxGDIRefData *CloneGDIRefData(const wxGDIRefData *data) const; + virtual wxGDIRefData *CreateGDIRefData() const wxOVERRIDE; + virtual wxGDIRefData *CloneGDIRefData(const wxGDIRefData *data) const wxOVERRIDE; private: diff --git a/interface/wx/font.h b/interface/wx/font.h index d1204b49dd..acbb5d0500 100644 --- a/interface/wx/font.h +++ b/interface/wx/font.h @@ -61,13 +61,27 @@ enum wxFontStyle /** Font weights. + + The values of this enum correspond to the CSS font weight specifications, + see https://www.w3.org/TR/css-fonts-4/#font-weight-prop, with the addition of + one font weight bolder than heavy + + */ enum wxFontWeight { - wxFONTWEIGHT_NORMAL = wxNORMAL, //!< Normal font. - wxFONTWEIGHT_LIGHT = wxLIGHT, //!< Light font. - wxFONTWEIGHT_BOLD = wxBOLD, //!< Bold font. - wxFONTWEIGHT_MAX + wxFONTWEIGHT_INVALID = 0, //!< Invalid font weight. @since 3.1.2 + wxFONTWEIGHT_THIN = 100, //!< Thin font (weight = 100). @since 3.1.2 + wxFONTWEIGHT_EXTRALIGHT = 200, //!< Extra Light (Ultra Light) font (weight = 200). @since 3.1.2 + wxFONTWEIGHT_LIGHT = 300, //!< Light font (weight = 300). + wxFONTWEIGHT_NORMAL = 400, //!< Normal font (weight = 400). + wxFONTWEIGHT_MEDIUM = 500, //!< Medium font (weight = 500). @since 3.1.2 + wxFONTWEIGHT_SEMIBOLD = 600, //!< Semi Bold (Demi Bold) font (weight = 600). @since 3.1.2 + wxFONTWEIGHT_BOLD = 700, //!< Bold font (weight = 700). + wxFONTWEIGHT_EXTRABOLD = 800, //!< Extra Bold (Ultra Bold) font (weight = 800). @since 3.1.2 + wxFONTWEIGHT_HEAVY = 900, //!< Heavy (Black) font (weight = 900). @since 3.1.2 + wxFONTWEIGHT_EXTRAHEAVY = 1000, //!< Extra Heavy font (weight = 1000). @since 3.1.2 + wxFONTWEIGHT_MAX = wxFONTWEIGHT_EXTRAHEAVY }; /** @@ -698,12 +712,24 @@ public: static bool AddPrivateFont(const wxString& filename); /** - Gets the point size. + Gets the point size as an integer number. - @see SetPointSize() + This function is kept for compatibility reasons. New code should use + GetFractionalPointSize() and support fractional point sizes. + + @see SetPointSize(), @see GetFractionalPointSize() */ virtual int GetPointSize() const; + /** + Gets the point size as a floating number. + + @see SetPointSize(float) + + @since 3.1.2 + */ + virtual float GetFractionalPointSize() const; + /** Gets the pixel size. @@ -745,6 +771,18 @@ public: */ virtual wxFontWeight GetWeight() const; + /** + Gets the font weight as an integer value. + + See ::wxFontWeight for a list of valid weight identifiers and their corresponding integer value. + + @see SetWeight() + @see SetNumericWeight() + + @since 3.1.2 + */ + virtual int GetNumericWeight() const; + /** Returns @true if the font is a fixed width (or monospaced) font, @false if it is a proportional one or font is invalid. @@ -1019,7 +1057,7 @@ public: bool SetNativeFontInfoUserDesc(const wxString& info); void SetNativeFontInfo(const wxNativeFontInfo& info); - + /** Sets the point size. @@ -1027,11 +1065,13 @@ public: (25.4 mm): it is approximately 0.0139 inch or 352.8 um. @param pointSize - Size in points. + Size in points. This can also be a fractional point size like 11.5. + Note that until wxWidgets 3.1.2, the size had to be an integer number + (and the type of this parameter was @c int). @see GetPointSize() */ - virtual void SetPointSize(int pointSize); + virtual void SetPointSize(float pointSize); /** Sets the pixel size. @@ -1114,6 +1154,19 @@ public: */ virtual void SetWeight(wxFontWeight weight); + /** + Sets the font weight using an integer value. + + See ::wxFontWeight for a list of valid weight identifiers and their + corresponding integer value. + + @param weight + An integer value int the range 1-1000. + + @see GetNumericWeight() + */ + virtual void SetNumericWeight(int weight); + //@} @@ -1186,7 +1239,7 @@ public: const wxString& faceName = wxEmptyString, wxFontEncoding encoding = wxFONTENCODING_DEFAULT); - + static wxFont *New(const wxNativeFontInfo& nativeInfo); static wxFont *New(const wxString& nativeInfoString); @@ -1265,7 +1318,7 @@ public: /** Finds a font of the given specification, or creates one and adds it to the list. See the @ref wxFont "wxFont constructor" for details of the arguments. - + @since 3.1.1 */ wxFont* FindOrCreateFont(const wxFontInfo& fontInfo); diff --git a/interface/wx/fontutil.h b/interface/wx/fontutil.h index 5dd323c435..81dfcd3310 100644 --- a/interface/wx/fontutil.h +++ b/interface/wx/fontutil.h @@ -29,19 +29,22 @@ public: void Init(); void InitFromFont(const wxFont& font); - + int GetPointSize() const; + float GetFractionalPointSize() const; wxSize GetPixelSize() const; wxFontStyle GetStyle() const; + int GetNumericWeight() const; wxFontWeight GetWeight() const; bool GetUnderlined() const; wxString GetFaceName() const; wxFontFamily GetFamily() const; wxFontEncoding GetEncoding() const; - void SetPointSize(int pointsize); + void SetPointSize(float pointsize); void SetPixelSize(const wxSize& pixelSize); void SetStyle(wxFontStyle style); + void SetNumericWeight(int weight); void SetWeight(wxFontWeight weight); void SetUnderlined(bool underlined); bool SetFaceName(const wxString& facename); diff --git a/misc/schema/xrc_schema.rnc b/misc/schema/xrc_schema.rnc index c0d60d10ef..df73748b1a 100644 --- a/misc/schema/xrc_schema.rnc +++ b/misc/schema/xrc_schema.rnc @@ -456,7 +456,9 @@ t_bitmap = t_url?, t_font = ( [xrc:p="o"] element size {_, t_integer }* & [xrc:p="o"] element style {_, ("normal" | "italic" | "slant") }* & - [xrc:p="o"] element weight {_, ("normal" | "bold" | "light") }* & + [xrc:p="o"] element weight {_, ("normal" | "thin" | "extralight" | "light" | + "medium" | "semibold" | "bold" | "extrabold" | + "heavy" | "extraheavy") }* & [xrc:p="o"] element family {_, ("roman" | "script" | "decorative" | "swiss" | "modern" | "teletype") }* & [xrc:p="o"] element underlined {_, t_bool }* & diff --git a/src/common/dcsvg.cpp b/src/common/dcsvg.cpp index 9eb2f4f0fb..7a02bebb4f 100644 --- a/src/common/dcsvg.cpp +++ b/src/common/dcsvg.cpp @@ -576,27 +576,7 @@ void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoor else s += wxS("style=\" "); - wxString fontweight; - switch (m_font.GetWeight()) - { - case wxFONTWEIGHT_MAX: - wxFAIL_MSG(wxS("invalid font weight value")); - wxFALLTHROUGH; - - case wxFONTWEIGHT_NORMAL: - fontweight = wxS("normal"); - break; - - case wxFONTWEIGHT_LIGHT: - fontweight = wxS("lighter"); - break; - - case wxFONTWEIGHT_BOLD: - fontweight = wxS("bold"); - break; - } - - wxASSERT_MSG(!fontweight.empty(), wxS("unknown font weight value")); + wxString fontweight = wxString::Format(wxS("%d"),m_font.GetWeight()); s += wxS("font-weight:") + fontweight + wxS("; "); diff --git a/src/common/fontcmn.cpp b/src/common/fontcmn.cpp index ea249bad90..1d8038e85b 100644 --- a/src/common/fontcmn.cpp +++ b/src/common/fontcmn.cpp @@ -92,9 +92,16 @@ wxENUM_MEMBER( wxFONTSTYLE_SLANT ) wxEND_ENUM( wxFontStyle ) wxBEGIN_ENUM( wxFontWeight ) -wxENUM_MEMBER( wxFONTWEIGHT_NORMAL ) +wxENUM_MEMBER( wxFONTWEIGHT_THIN ) +wxENUM_MEMBER( wxFONTWEIGHT_EXTRALIGHT ) wxENUM_MEMBER( wxFONTWEIGHT_LIGHT ) +wxENUM_MEMBER( wxFONTWEIGHT_NORMAL ) +wxENUM_MEMBER( wxFONTWEIGHT_MEDIUM ) +wxENUM_MEMBER( wxFONTWEIGHT_SEMIBOLD ) wxENUM_MEMBER( wxFONTWEIGHT_BOLD ) +wxENUM_MEMBER( wxFONTWEIGHT_EXTRABOLD ) +wxENUM_MEMBER( wxFONTWEIGHT_HEAVY ) +wxENUM_MEMBER( wxFONTWEIGHT_EXTRAHEAVY ) wxEND_ENUM( wxFontWeight ) wxIMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont, wxGDIObject, "wx/font.h"); @@ -225,6 +232,12 @@ bool wxFontBase::IsFixedWidth() const return GetFamily() == wxFONTFAMILY_TELETYPE; } +int wxFontBase::GetPointSize() const +{ + return wxRound(GetFractionalPointSize()); +} + + wxSize wxFontBase::GetPixelSize() const { wxScreenDC dc; @@ -455,9 +468,16 @@ wxString wxFontBase::GetWeightString() const switch ( GetWeight() ) { - case wxFONTWEIGHT_NORMAL: return "wxFONTWEIGHT_NORMAL"; - case wxFONTWEIGHT_BOLD: return "wxFONTWEIGHT_BOLD"; + case wxFONTWEIGHT_THIN: return "wxFONTWEIGHT_THIN"; + case wxFONTWEIGHT_EXTRALIGHT: return "wxFONTWEIGHT_EXTRALIGHT"; case wxFONTWEIGHT_LIGHT: return "wxFONTWEIGHT_LIGHT"; + case wxFONTWEIGHT_NORMAL: return "wxFONTWEIGHT_NORMAL"; + case wxFONTWEIGHT_MEDIUM: return "wxFONTWEIGHT_MEDIUM"; + case wxFONTWEIGHT_SEMIBOLD: return "wxFONTWEIGHT_SEMIBOLD"; + case wxFONTWEIGHT_BOLD: return "wxFONTWEIGHT_BOLD"; + case wxFONTWEIGHT_EXTRABOLD: return "wxFONTWEIGHT_EXTRABOLD"; + case wxFONTWEIGHT_HEAVY: return "wxFONTWEIGHT_HEAVY"; + case wxFONTWEIGHT_EXTRAHEAVY: return "wxFONTWEIGHT_EXTRAHEAVY"; default: return "wxFONTWEIGHT_DEFAULT"; } } @@ -816,13 +836,41 @@ wxString wxNativeFontInfo::ToUserString() const case wxFONTWEIGHT_NORMAL: break; + case wxFONTWEIGHT_THIN: + desc << _(" thin"); + break; + + case wxFONTWEIGHT_EXTRALIGHT: + desc << _(" extra light"); + break; + case wxFONTWEIGHT_LIGHT: desc << _(" light"); break; + case wxFONTWEIGHT_MEDIUM: + desc << _(" medium"); + break; + + case wxFONTWEIGHT_SEMIBOLD: + desc << _(" semi bold"); + break; + case wxFONTWEIGHT_BOLD: desc << _(" bold"); break; + + case wxFONTWEIGHT_EXTRABOLD: + desc << _(" extra bold"); + break; + + case wxFONTWEIGHT_HEAVY: + desc << _(" heavy"); + break; + + case wxFONTWEIGHT_EXTRAHEAVY: + desc << _(" extra heavy"); + break; } switch ( GetStyle() ) @@ -938,6 +986,8 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) bool encodingfound = false; #endif bool insideQuotes = false; + bool extraQualifierFound = false; + bool semiQualifierFound = false; while ( tokenizer.HasMoreTokens() ) { @@ -988,21 +1038,85 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) SetUnderlined(true); SetStrikethrough(true); } - else if ( token == wxT("light") || token == _("light") ) + else if ( token == wxS("thin") || token == _("thin") ) { - SetWeight(wxFONTWEIGHT_LIGHT); + SetWeight(wxFONTWEIGHT_THIN); weightfound = true; } - else if ( token == wxT("bold") || token == _("bold") ) + else if ( token == wxS("extra") || token == wxS("ultra")) { - SetWeight(wxFONTWEIGHT_BOLD); + extraQualifierFound = true; + } + else if ( token == wxS("semi") || token == wxS("demi") ) + { + semiQualifierFound = true; + } + else if ( token == wxS("extralight") || token == _("extralight") ) + { + SetWeight(wxFONTWEIGHT_EXTRALIGHT); + weightfound = true; + } + else if ( token == wxS("light") || token == _("light") ) + { + if ( extraQualifierFound ) + SetWeight(wxFONTWEIGHT_EXTRALIGHT); + else + SetWeight(wxFONTWEIGHT_LIGHT); + weightfound = true; + } + else if ( token == wxS("normal") || token == _("normal") ) + { + SetWeight(wxFONTWEIGHT_NORMAL); + weightfound = true; + } + else if ( token == wxS("medium") || token == _("medium") ) + { + SetWeight(wxFONTWEIGHT_MEDIUM); + weightfound = true; + } + else if ( token == wxS("semibold") || token == _("semibold") ) + { + SetWeight(wxFONTWEIGHT_SEMIBOLD); + weightfound = true; + } + else if ( token == wxS("bold") || token == _("bold") ) + { + if ( extraQualifierFound ) + SetWeight(wxFONTWEIGHT_EXTRABOLD); + else if ( semiQualifierFound ) + SetWeight(wxFONTWEIGHT_SEMIBOLD); + else + SetWeight(wxFONTWEIGHT_BOLD); + weightfound = true; + } + else if ( token == wxS("extrabold") || token == _("extrabold") ) + { + SetWeight(wxFONTWEIGHT_EXTRABOLD); + weightfound = true; + } + else if ( token == wxS("semibold") || token == _("semibold") ) + { + SetWeight(wxFONTWEIGHT_SEMIBOLD); + weightfound = true; + } + else if ( token == wxS("heavy") || token == _("heavy") ) + { + if ( extraQualifierFound ) + SetWeight(wxFONTWEIGHT_EXTRAHEAVY); + else + SetWeight(wxFONTWEIGHT_HEAVY); + weightfound = true; + } + else if ( token == wxS("extraheavy") || token == _("extraheavy") ) + { + SetWeight(wxFONTWEIGHT_EXTRAHEAVY); weightfound = true; } else if ( token == wxT("italic") || token == _("italic") ) { SetStyle(wxFONTSTYLE_ITALIC); } - else if ( token.ToULong(&size) ) + else if ( token.ToULong(&size ) ) { SetPointSize(size); pointsizefound = true; @@ -1116,6 +1230,41 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) #endif // generic or wxMSW +// compatibility functions using old API implemented using numeric weight values + +wxFontWeight wxNativeFontInfo::GetWeight() const +{ + // round to nearest hundredth = wxFONTWEIGHT_ constant + int weight = ((GetNumericWeight() + 50) / 100) * 100; + + if (weight < wxFONTWEIGHT_THIN) + weight = wxFONTWEIGHT_THIN; + if (weight > wxFONTWEIGHT_MAX) + weight = wxFONTWEIGHT_MAX; + + return (wxFontWeight)weight; +} + +void wxNativeFontInfo::SetWeight(wxFontWeight weight) +{ + // deal with compatibility constants + if (weight >= 90 && weight <= 92) + { + if (weight == 90 /* wxNORMAL */) + weight = wxFONTWEIGHT_NORMAL; + else if (weight == 91 /* wxLIGHT */) + weight = wxFONTWEIGHT_LIGHT; + else if (weight == 92 /* wxBOLD */) + weight = wxFONTWEIGHT_BOLD; + } + + wxASSERT(weight > wxFONTWEIGHT_INVALID || weight <= wxFONTWEIGHT_MAX); + wxASSERT(weight % 100 == 0); + + wxFontWeight formerWeight = GetWeight(); + if (formerWeight != weight) + SetNumericWeight(weight); +} // wxFont <-> wxString utilities, used by wxConfig wxString wxToString(const wxFontBase& font) diff --git a/src/gtk/font.cpp b/src/gtk/font.cpp index 96403a8bbb..bcd3ffbbdd 100644 --- a/src/gtk/font.cpp +++ b/src/gtk/font.cpp @@ -65,10 +65,11 @@ public: // setters: all of them also take care to modify m_nativeFontInfo if we // have it so as to not lose the information not carried by our fields - void SetPointSize(int pointSize); + void SetPointSize(float pointSize); void SetFamily(wxFontFamily family); void SetStyle(wxFontStyle style); void SetWeight(wxFontWeight weight); + void SetNumericWeight(int weight); void SetUnderlined(bool underlined); void SetStrikethrough(bool strikethrough); bool SetFaceName(const wxString& facename); @@ -190,7 +191,7 @@ wxFontRefData::~wxFontRefData() // wxFontRefData SetXXX() // ---------------------------------------------------------------------------- -void wxFontRefData::SetPointSize(int pointSize) +void wxFontRefData::SetPointSize(float pointSize) { m_nativeFontInfo.SetPointSize(pointSize); } @@ -239,6 +240,11 @@ void wxFontRefData::SetWeight(wxFontWeight weight) m_nativeFontInfo.SetWeight(weight); } +void wxFontRefData::SetNumericWeight(int weight) +{ + m_nativeFontInfo.SetNumericWeight(weight); +} + void wxFontRefData::SetUnderlined(bool underlined) { m_nativeFontInfo.SetUnderlined(underlined); @@ -340,11 +346,11 @@ wxFont::~wxFont() // accessors // ---------------------------------------------------------------------------- -int wxFont::GetPointSize() const +float wxFont::GetFractionalPointSize() const { wxCHECK_MSG( IsOk(), 0, wxT("invalid font") ); - return M_FONTDATA->m_nativeFontInfo.GetPointSize(); + return M_FONTDATA->m_nativeFontInfo.GetFractionalPointSize(); } wxString wxFont::GetFaceName() const @@ -368,11 +374,18 @@ wxFontStyle wxFont::GetStyle() const wxFontWeight wxFont::GetWeight() const { - wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font") ); + wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, "invalid font" ); return M_FONTDATA->m_nativeFontInfo.GetWeight(); } +int wxFont::GetNumericWeight() const +{ + wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, "invalid font" ); + + return M_FONTDATA->m_nativeFontInfo.GetNumericWeight(); +} + bool wxFont::GetUnderlined() const { wxCHECK_MSG( IsOk(), false, wxT("invalid font") ); @@ -413,7 +426,7 @@ bool wxFont::IsFixedWidth() const // change font attributes // ---------------------------------------------------------------------------- -void wxFont::SetPointSize(int pointSize) +void wxFont::SetPointSize(float pointSize) { AllocExclusive(); @@ -441,6 +454,13 @@ void wxFont::SetWeight(wxFontWeight weight) M_FONTDATA->SetWeight(weight); } +void wxFont::SetNumericWeight(int weight) +{ + AllocExclusive(); + + M_FONTDATA->SetNumericWeight(weight); +} + bool wxFont::SetFaceName(const wxString& faceName) { AllocExclusive(); @@ -650,3 +670,4 @@ bool wxFontBase::AddPrivateFont(const wxString& filename) } #endif // wxUSE_PRIVATE_FONTS + diff --git a/src/msw/font.cpp b/src/msw/font.cpp index 27dc7cfed1..a356e10c50 100644 --- a/src/msw/font.cpp +++ b/src/msw/font.cpp @@ -98,7 +98,7 @@ public: void Free(); // all wxFont accessors - int GetPointSize() const + float GetFractionalPointSize() const { return m_nativeFontInfo.GetPointSize(); } @@ -128,6 +128,11 @@ public: return m_nativeFontInfo.GetWeight(); } + int GetNumericWeight() const + { + return m_nativeFontInfo.GetNumericWeight(); + } + bool GetUnderlined() const { return m_nativeFontInfo.GetUnderlined(); @@ -176,7 +181,7 @@ public: // ... and setters: notice that all of them invalidate the currently // allocated HFONT, if any, so that the next call to GetHFONT() recreates a // new one - void SetPointSize(int pointSize) + void SetPointSize(float pointSize) { Free(); @@ -216,6 +221,13 @@ public: m_nativeFontInfo.SetWeight(weight); } + void SetNumericWeight(int weight) + { + Free(); + + m_nativeFontInfo.SetNumericWeight(weight); + } + bool SetFaceName(const wxString& faceName) { Free(); @@ -437,6 +449,11 @@ void wxNativeFontInfo::Init() } int wxNativeFontInfo::GetPointSize() const +{ + return wxRound(GetFractionalPointSize()); +} + +float wxNativeFontInfo::GetFractionalPointSize() const { // FIXME: using the screen here results in incorrect font size calculation // for printing! @@ -459,15 +476,9 @@ wxFontStyle wxNativeFontInfo::GetStyle() const return lf.lfItalic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL; } -wxFontWeight wxNativeFontInfo::GetWeight() const +int wxNativeFontInfo::GetNumericWeight() const { - if ( lf.lfWeight <= 300 ) - return wxFONTWEIGHT_LIGHT; - - if ( lf.lfWeight >= 600 ) - return wxFONTWEIGHT_BOLD; - - return wxFONTWEIGHT_NORMAL; + return lf.lfWeight; } bool wxNativeFontInfo::GetUnderlined() const @@ -530,7 +541,7 @@ wxFontEncoding wxNativeFontInfo::GetEncoding() const return wxGetFontEncFromCharSet(lf.lfCharSet); } -void wxNativeFontInfo::SetPointSize(int pointsize) +void wxNativeFontInfo::SetPointSize(float pointsize) { // FIXME: using the screen here results in incorrect font size calculation // for printing! @@ -573,26 +584,9 @@ void wxNativeFontInfo::SetStyle(wxFontStyle style) } } -void wxNativeFontInfo::SetWeight(wxFontWeight weight) +void wxNativeFontInfo::SetNumericWeight(int weight) { - switch ( weight ) - { - default: - wxFAIL_MSG( "unknown font weight" ); - // fall through - - case wxFONTWEIGHT_NORMAL: - lf.lfWeight = FW_NORMAL; - break; - - case wxFONTWEIGHT_LIGHT: - lf.lfWeight = FW_LIGHT; - break; - - case wxFONTWEIGHT_BOLD: - lf.lfWeight = FW_BOLD; - break; - } + lf.lfWeight = weight; } void wxNativeFontInfo::SetUnderlined(bool underlined) @@ -906,7 +900,7 @@ bool wxFont::IsFree() const // change font attribute: we recreate font when doing it // ---------------------------------------------------------------------------- -void wxFont::SetPointSize(int pointSize) +void wxFont::SetPointSize(float pointSize) { AllocExclusive(); @@ -942,6 +936,13 @@ void wxFont::SetWeight(wxFontWeight weight) M_FONTDATA->SetWeight(weight); } +void wxFont::SetNumericWeight(int weight) +{ + AllocExclusive(); + + M_FONTDATA->SetNumericWeight(weight); +} + bool wxFont::SetFaceName(const wxString& faceName) { AllocExclusive(); @@ -991,11 +992,11 @@ void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info) // accessors // ---------------------------------------------------------------------------- -int wxFont::GetPointSize() const +float wxFont::GetFractionalPointSize() const { wxCHECK_MSG( IsOk(), 0, wxT("invalid font") ); - return M_FONTDATA->GetPointSize(); + return M_FONTDATA->GetFractionalPointSize(); } wxSize wxFont::GetPixelSize() const @@ -1026,11 +1027,18 @@ wxFontStyle wxFont::GetStyle() const wxFontWeight wxFont::GetWeight() const { - wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font") ); + wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, "invalid font" ); return M_FONTDATA->GetWeight(); } +int wxFont::GetNumericWeight() const +{ + wxCHECK_MSG(IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font")); + + return M_FONTDATA->GetNumericWeight(); +} + bool wxFont::GetUnderlined() const { wxCHECK_MSG( IsOk(), false, wxT("invalid font") ); diff --git a/src/osx/carbon/font.cpp b/src/osx/carbon/font.cpp index 601020702b..e74e078d14 100644 --- a/src/osx/carbon/font.cpp +++ b/src/osx/carbon/font.cpp @@ -13,12 +13,12 @@ #include "wx/font.h" #ifndef WX_PRECOMP - #include "wx/string.h" - #include "wx/utils.h" - #include "wx/intl.h" - #include "wx/gdicmn.h" - #include "wx/log.h" - #include "wx/math.h" +#include "wx/string.h" +#include "wx/utils.h" +#include "wx/intl.h" +#include "wx/gdicmn.h" +#include "wx/log.h" +#include "wx/math.h" #endif #include "wx/fontutil.h" @@ -31,164 +31,292 @@ #include #include -class WXDLLEXPORT wxFontRefData: public wxGDIRefData +#define TRACE_CTFONT "ctfont" + +class WXDLLEXPORT wxFontRefData : public wxGDIRefData { public: - wxFontRefData() { - Init(); - m_info.Init(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, - false, false, wxEmptyString, wxFONTENCODING_DEFAULT); + Init(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, + false, false, wxEmptyString, wxFONTENCODING_DEFAULT); + } + + wxFontRefData(float size, + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, + bool underlined, + bool strikethrough, + const wxString& faceName, + wxFontEncoding encoding) + { + Init(size, family, style, weight, underlined, strikethrough, faceName, encoding); } wxFontRefData(const wxFontRefData& data); - wxFontRefData( const wxNativeFontInfo& info ) : m_info(info) + wxFontRefData(const wxNativeFontInfo& info) { Init(); + m_info.Init(info); } - wxFontRefData(wxOSXSystemFont font, int size); - - wxFontRefData( wxUint32 coreTextFontType ); - wxFontRefData( CTFontRef font ); - wxFontRefData( CTFontDescriptorRef fontdescriptor, int size ); + wxFontRefData(CTFontRef font); virtual ~wxFontRefData(); - void SetPointSize( int size ) + float GetFractionalPointSize() const { return m_info.GetFractionalPointSize(); } + + wxFontFamily GetFamily() const { return m_info.GetFamily(); } + + wxFontStyle GetStyle() const { return m_info.GetStyle(); } + + wxFontWeight GetWeight() const { return m_info.GetWeight(); } + + int GetNumericWeight() const { return m_info.GetNumericWeight(); } + + bool GetUnderlined() const { return m_info.GetUnderlined(); } + + bool GetStrikethrough() const { return m_info.GetStrikethrough(); } + + wxString GetFaceName() const { return m_info.GetFaceName(); } + + wxFontEncoding GetEncoding() const { return m_info.GetEncoding(); } + + bool IsFixedWidth() const; + + CTFontRef OSXGetCTFont() const; + + CFDictionaryRef OSXGetCTFontAttributes() const; + + CGFontRef OSXGetCGFont() const; + + const wxNativeFontInfo& GetNativeFontInfo() const; + + void SetPointSize(float size) { - if( GetPointSize() != size ) + if (GetFractionalPointSize() != size) { m_info.SetPointSize(size); Free(); } } - int GetPointSize() const { return m_info.GetPointSize(); } - - void SetFamily( wxFontFamily family ) + void SetFamily(wxFontFamily family) { - if ( m_info.m_family != family ) + if (m_info.GetFamily() != family) { - m_info.SetFamily( family ); + m_info.SetFamily(family); Free(); } } - wxFontFamily GetFamily() const { return m_info.GetFamily(); } - - void SetStyle( wxFontStyle style ) + void SetStyle(wxFontStyle style) { - if ( m_info.m_style != style ) + if (m_info.GetStyle() != style) { - m_info.SetStyle( style ); + m_info.SetStyle(style); Free(); } } - - wxFontStyle GetStyle() const { return m_info.GetStyle(); } - - void SetWeight( wxFontWeight weight ) + void SetWeight(wxFontWeight weight) { - if ( m_info.m_weight != weight ) + if (m_info.GetWeight() != weight) { - m_info.SetWeight( weight ); + m_info.SetWeight(weight); Free(); } } - - wxFontWeight GetWeight() const { return m_info.GetWeight(); } - - void SetStrikethrough( bool s ) + void SetNumericWeight(int weight) { - if ( m_info.m_strikethrough != s ) + if (m_info.GetNumericWeight() != weight) { - m_info.SetStrikethrough( s ); + m_info.SetNumericWeight(weight); Free(); } } - void SetUnderlined( bool u ) + void SetStrikethrough(bool s) { - if ( m_info.m_underlined != u ) + if (m_info.GetStrikethrough() != s) { - m_info.SetUnderlined( u ); + m_info.SetStrikethrough(s); Free(); } } - bool GetUnderlined() const { return m_info.GetUnderlined(); } - bool GetStrikethrough() const { return m_info.GetStrikethrough(); } - - void SetFaceName( const wxString& facename ) + void SetUnderlined(bool u) { - if ( m_info.m_faceName != facename ) + if (m_info.GetUnderlined() != u) { - m_info.SetFaceName( facename ); + m_info.SetUnderlined(u); Free(); } } - wxString GetFaceName() const { return m_info.GetFaceName(); } - - void SetEncoding( wxFontEncoding encoding ) + void SetFaceName(const wxString& facename) { - if ( m_info.m_encoding != encoding ) + if (m_info.GetFaceName() != facename) { - m_info.SetEncoding( encoding ); + m_info.SetFaceName(facename); Free(); } } - wxFontEncoding GetEncoding() const { return m_info.GetEncoding(); } - - bool IsFixedWidth() const; + void SetEncoding(wxFontEncoding encoding) + { + if (m_info.GetEncoding() != encoding) + { + m_info.SetEncoding(encoding); + Free(); + } + } void Free(); - void MacFindFont(); - + void Alloc(); protected: // common part of all ctors void Init(); -public: - bool m_fontValid; + void Init(float size, + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, + bool underlined, + bool strikethrough, + const wxString& faceName, + wxFontEncoding encoding); + void SetFont(CTFontRef font); + void AllocIfNeeded() const; + wxCFRef m_ctFont; - wxCFRef m_ctFontAttributes; + wxCFMutableDictionaryRef m_ctFontAttributes; wxCFRef m_cgFont; - wxNativeFontInfo m_info; + wxNativeFontInfo m_info; }; -#define M_FONTDATA ((wxFontRefData*)m_refData) - -wxFontRefData::wxFontRefData(const wxFontRefData& data) : wxGDIRefData() -{ - Init(); - m_info = data.m_info; - m_fontValid = data.m_fontValid; - m_ctFont = data.m_ctFont; - m_ctFontAttributes = data.m_ctFontAttributes; - m_cgFont = data.m_cgFont; -} - // ============================================================================ // implementation // ============================================================================ wxStringToStringHashMap gs_FontFamilyToPSName; -static CTFontDescriptorRef wxMacCreateCTFontDescriptor(CFStringRef iFamilyName, CTFontSymbolicTraits iTraits ); + +namespace +{ + const int kCTWeightsCount = 12; + static CGFloat gCTWeights[kCTWeightsCount] = { + -1.000, // 0 + -0.800, // 100 + -0.600, // 200 + -0.400, // 300 + 0.000, // 400 + 0.230, // 500 + 0.300, // 600 + 0.400, // 700 + 0.560, // 800 + 0.620, // 900 + 0.750, // 1000 + }; + + int CTWeightToWX(CGFloat weight) + { + for (int i = 0; i < kCTWeightsCount; ++i) + { + if ( (weight - gCTWeights[i]) < (gCTWeights[i+1]-weight) ) + return i * 100; + } + return 1000; + } + + CGFloat WXWeightToCT(int w) + { + if (w < 0) + w = 0; + else if (w > 1000) + w = 1000; + + return gCTWeights[w / 100]; + } + + wxString FamilyToFaceName(wxFontFamily family) + { + wxString faceName; + + switch (family) + { + case wxFONTFAMILY_DEFAULT: + faceName = wxT("Lucida Grande"); + break; + + case wxFONTFAMILY_SCRIPT: + case wxFONTFAMILY_ROMAN: + case wxFONTFAMILY_DECORATIVE: + faceName = wxT("Times"); + break; + + case wxFONTFAMILY_SWISS: + faceName = wxT("Helvetica"); + break; + + case wxFONTFAMILY_MODERN: + case wxFONTFAMILY_TELETYPE: + faceName = wxT("Courier"); + break; + + default: + faceName = wxT("Times"); + break; + } + + return faceName; + } + +} // anonymous namespace // ---------------------------------------------------------------------------- // wxFontRefData // ---------------------------------------------------------------------------- +#define M_FONTDATA ((wxFontRefData*)m_refData) + +wxFontRefData::wxFontRefData(const wxFontRefData& data) +: wxGDIRefData() +{ + Init(); + m_info = data.m_info; + m_ctFont = data.m_ctFont; + m_ctFontAttributes = data.m_ctFontAttributes; + m_cgFont = data.m_cgFont; +} + void wxFontRefData::Init() { - m_fontValid = false; + m_info.Init(); +} + +void wxFontRefData::Init(float size, + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, + bool underlined, + bool strikethrough, + const wxString& faceName, + wxFontEncoding encoding) +{ + m_info.Init(); + if ( !faceName.empty() ) + SetFaceName(faceName); + else + SetFamily(family); + SetPointSize(size < 0 ? wxNORMAL_FONT->GetFractionalPointSize() : size); + SetWeight(weight); + SetStyle(style); + SetUnderlined(underlined); + SetStrikethrough(strikethrough); + SetEncoding(encoding); } wxFontRefData::~wxFontRefData() @@ -199,189 +327,161 @@ wxFontRefData::~wxFontRefData() void wxFontRefData::Free() { m_ctFont.reset(); + m_ctFontAttributes.reset(); m_cgFont.reset(); - m_fontValid = false; } -wxFontRefData::wxFontRefData(wxOSXSystemFont font, int size) +wxFontRefData::wxFontRefData(CTFontRef font) { - wxASSERT( font != wxOSX_SYSTEM_FONT_NONE ); Init(); - - { - CTFontUIFontType uifont = kCTFontSystemFontType; - switch( font ) - { - case wxOSX_SYSTEM_FONT_NORMAL: - uifont = kCTFontSystemFontType; - break; - case wxOSX_SYSTEM_FONT_BOLD: - uifont = kCTFontEmphasizedSystemFontType; - break; - case wxOSX_SYSTEM_FONT_SMALL: - uifont = kCTFontSmallSystemFontType; - break; - case wxOSX_SYSTEM_FONT_SMALL_BOLD: - uifont = kCTFontSmallEmphasizedSystemFontType; - break; - case wxOSX_SYSTEM_FONT_MINI: - uifont = kCTFontMiniSystemFontType; - break; - case wxOSX_SYSTEM_FONT_MINI_BOLD: - uifont = kCTFontMiniEmphasizedSystemFontType; - break; - case wxOSX_SYSTEM_FONT_LABELS: - uifont = kCTFontLabelFontType; - break; - case wxOSX_SYSTEM_FONT_VIEWS: - uifont = kCTFontViewsFontType; - break; - default: - break; - } - m_ctFont.reset(CTFontCreateUIFontForLanguage( uifont, (CGFloat) size, NULL )); - CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - m_ctFontAttributes.reset(dict); - CFDictionarySetValue(dict, kCTFontAttributeName, m_ctFont.get() ); - CFDictionarySetValue(dict, kCTForegroundColorFromContextAttributeName, kCFBooleanTrue); - - wxCFRef descr; - descr.reset( CTFontCopyFontDescriptor( m_ctFont ) ); - m_info.Init(descr); - } - - m_fontValid = true; + SetFont(font); + m_info.InitFromFont(font); } -static const CGAffineTransform kSlantTransform = CGAffineTransformMake( 1, 0, tan(wxDegToRad(11)), 1, 0, 0 ); +void wxFontRefData::SetFont(CTFontRef font) +{ + m_ctFont.reset(wxCFRetain(font)); + + wxCFMutableDictionaryRef dict; + dict.SetValue(kCTFontAttributeName, m_ctFont.get()); + dict.SetValue(kCTForegroundColorFromContextAttributeName, kCFBooleanTrue); + + m_ctFontAttributes = dict; +} + +static const CGAffineTransform kSlantTransform = CGAffineTransformMake(1, 0, tan(wxDegToRad(11)), 1, 0, 0); namespace { - -struct CachedFontEntry { - wxCFRef< CTFontRef > font; - wxCFRef< CFDictionaryRef > fontAttributes; -} ; - + +struct CachedFontEntry +{ + CachedFontEntry() + { + used = false; + } + + wxCFRef font; + wxCFMutableDictionaryRef fontAttributes; + wxCFRef cgFont; + bool used; +}; + } // anonymous namespace -void wxFontRefData::MacFindFont() +void wxFontRefData::AllocIfNeeded() const { - if ( m_fontValid ) - return; + if (!m_ctFont) + const_cast(this)->Alloc(); - wxCHECK_RET( m_info.m_pointSize > 0, wxT("Point size should not be zero.") ); +} +void wxFontRefData::Alloc() +{ + wxCHECK_RET(m_info.GetPointSize() > 0, wxT("Point size should not be zero.")); + + // use font caching, we cache a font with a certain size and a font with just any size for faster creation + wxString lookupnameNoSize = wxString::Format("%s_%d_%d", m_info.GetFamilyName(), (int)m_info.GetStyle(), m_info.GetNumericWeight()); + + wxString lookupnameWithSize = wxString::Format("%s_%d_%d_%.2f", m_info.GetFamilyName(), (int)m_info.GetStyle(), m_info.GetNumericWeight(), m_info.GetFractionalPointSize()); + + static std::map fontcache; + + CachedFontEntry& entryWithSize = fontcache[lookupnameWithSize]; + if (entryWithSize.used) { - CTFontSymbolicTraits traits = 0; - - if (m_info.m_weight == wxFONTWEIGHT_BOLD) - traits |= kCTFontBoldTrait; - if (m_info.m_style == wxFONTSTYLE_ITALIC || m_info.m_style == wxFONTSTYLE_SLANT) - traits |= kCTFontItalicTrait; - - // use font caching - wxString lookupnameWithSize = wxString::Format( "%s_%u_%d", m_info.m_faceName, traits, m_info.m_pointSize ); - - static std::map< wxString, CachedFontEntry > fontcache ; - - CachedFontEntry& entry = fontcache[ lookupnameWithSize ]; - m_ctFont = entry.font; - m_ctFontAttributes = entry.fontAttributes; - if ( m_ctFont ) + m_ctFont = entryWithSize.font; + m_ctFontAttributes = entryWithSize.fontAttributes; + } + else + { + CachedFontEntry& entryNoSize = fontcache[lookupnameNoSize]; + if ( entryNoSize.used ) { - // use cached version + m_ctFont = CTFontCreateCopyWithAttributes(entryNoSize.font, m_info.GetPointSize(), NULL, NULL); + m_ctFontAttributes = entryNoSize.fontAttributes.CreateCopy(); + m_ctFontAttributes.SetValue(kCTFontAttributeName,m_ctFont.get()); + m_cgFont = CTFontCopyGraphicsFont(m_ctFont, NULL); + entryWithSize.font = m_ctFont; + entryWithSize.cgFont = m_cgFont; + entryWithSize.cgFont = m_cgFont; + entryWithSize.fontAttributes = m_ctFontAttributes; + entryWithSize.used = true; } else { - CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - m_ctFontAttributes.reset(dict); - - wxStringToStringHashMap::const_iterator it = gs_FontFamilyToPSName.find(m_info.m_faceName); - - if ( it != gs_FontFamilyToPSName.end() ) + // emulate slant if necessary, the font descriptor itself carries that information, + // while the weight can only be determined properly from the generated font itself + const CGAffineTransform* remainingTransform = NULL; + if ( m_info.GetStyle() != wxFONTSTYLE_NORMAL && m_info.GetCTSlant(m_info.GetCTFontDescriptor()) < 0.01 ) + remainingTransform = &kSlantTransform; + + wxCFRef font = CTFontCreateWithFontDescriptor(m_info.GetCTFontDescriptor(), m_info.GetPointSize(), remainingTransform); + + // emulate weigth if necessary + int difference = m_info.GetNumericWeight() - CTWeightToWX(wxNativeFontInfo::GetCTWeight(font)); + + SetFont(font); + if ( difference != 0 ) { - m_ctFont.reset(CTFontCreateWithName( wxCFStringRef(it->second), m_info.m_pointSize , NULL )); - } - else - { - wxCFRef desc(wxMacCreateCTFontDescriptor(wxCFStringRef(m_info.m_faceName),0)); - m_ctFont.reset(CTFontCreateWithFontDescriptor(desc, m_info.m_pointSize , NULL )); - m_info.UpdateNamesMap(m_info.m_faceName, m_ctFont); - } - - if ( m_ctFont.get() == NULL ) - { - // TODO try fallbacks according to font type - m_ctFont.reset(CTFontCreateUIFontForLanguage( kCTFontSystemFontType, m_info.m_pointSize , NULL )); - } - else - { - if ( traits != 0 ) + if ( difference > 0 ) { - // attempt native font variant, if not available, fallback to italic emulation mode and remove bold - CTFontRef fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, NULL, traits, traits ); - if ( fontWithTraits == NULL ) - { - CTFontSymbolicTraits remainingTraits = traits; - const CGAffineTransform* remainingTransform = NULL; - - if( remainingTraits & kCTFontItalicTrait ) - { - remainingTraits &= ~kCTFontItalicTrait; - remainingTransform = &kSlantTransform; - if ( remainingTraits & kCTFontBoldTrait ) - { - // first try an emulated oblique with an existing bold font - fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, remainingTransform, remainingTraits, remainingTraits ); - if ( fontWithTraits == NULL ) - { - // try native oblique, emulate bold later - fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, NULL, kCTFontItalicTrait, kCTFontItalicTrait ); - } - else - { - remainingTraits &= ~kCTFontBoldTrait; - } - } - } - - // we have to emulate bold - if ( remainingTraits & kCTFontBoldTrait ) - { - // 3 times as thick, negative value because we want effect on stroke and fill (not only stroke) - const float strokewidth = -3.0; - CFDictionarySetValue(dict, kCTStrokeWidthAttributeName, CFNumberCreate( NULL, kCFNumberFloatType, &strokewidth)); - } - - if ( fontWithTraits == NULL ) - { - fontWithTraits = CTFontCreateCopyWithAttributes( m_ctFont, m_info.m_pointSize, remainingTransform, NULL ); - } - - } - if ( fontWithTraits != NULL ) - m_ctFont.reset(fontWithTraits); + // TODO: find better heuristics to determine target stroke width + CGFloat width = 0; + width = -1.0 * (1 + (difference / 100)); + m_ctFontAttributes.SetValue(kCTStrokeWidthAttributeName, width); + } + else + { + // we cannot emulate lighter fonts } } - CFDictionarySetValue(dict, kCTFontAttributeName, m_ctFont.get() ); - CFDictionarySetValue(dict, kCTForegroundColorFromContextAttributeName, kCFBooleanTrue); - - entry.font = m_ctFont; - entry.fontAttributes = m_ctFontAttributes; - } - m_cgFont.reset(CTFontCopyGraphicsFont(m_ctFont, NULL)); + m_cgFont = CTFontCopyGraphicsFont(m_ctFont, NULL); + entryWithSize.font = m_ctFont; + entryWithSize.cgFont = m_cgFont; + entryWithSize.fontAttributes = m_ctFontAttributes; + entryWithSize.used = true; + + entryNoSize.font = m_ctFont; + entryNoSize.fontAttributes = m_ctFontAttributes; + // no reason to copy cgFont as will have to be regenerated anyway + entryNoSize.used = true; + } } - m_fontValid = true; + m_cgFont.reset(CTFontCopyGraphicsFont(m_ctFont, NULL)); } - + bool wxFontRefData::IsFixedWidth() const { CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(m_ctFont); return (traits & kCTFontMonoSpaceTrait) != 0; } +CTFontRef wxFontRefData::OSXGetCTFont() const +{ + AllocIfNeeded(); + return m_ctFont; +} + +CFDictionaryRef wxFontRefData::OSXGetCTFontAttributes() const +{ + AllocIfNeeded(); + return m_ctFontAttributes; +} + +CGFontRef wxFontRefData::OSXGetCGFont() const +{ + AllocIfNeeded(); + return m_cgFont; +} + +const wxNativeFontInfo& wxFontRefData::GetNativeFontInfo() const +{ + AllocIfNeeded(); + return m_info; +} + // ---------------------------------------------------------------------------- // wxFont // ---------------------------------------------------------------------------- @@ -390,7 +490,7 @@ bool wxFont::Create(const wxNativeFontInfo& info) { UnRef(); - m_refData = new wxFontRefData( info ); + m_refData = new wxFontRefData(info); RealizeResource(); return true; @@ -398,77 +498,100 @@ bool wxFont::Create(const wxNativeFontInfo& info) wxFont::wxFont(wxOSXSystemFont font) { - m_refData = new wxFontRefData( font, 0 ); + wxASSERT(font != wxOSX_SYSTEM_FONT_NONE); + CTFontUIFontType uifont = kCTFontSystemFontType; + switch (font) + { + case wxOSX_SYSTEM_FONT_NORMAL: + uifont = kCTFontSystemFontType; + break; + case wxOSX_SYSTEM_FONT_BOLD: + uifont = kCTFontEmphasizedSystemFontType; + break; + case wxOSX_SYSTEM_FONT_SMALL: + uifont = kCTFontSmallSystemFontType; + break; + case wxOSX_SYSTEM_FONT_SMALL_BOLD: + uifont = kCTFontSmallEmphasizedSystemFontType; + break; + case wxOSX_SYSTEM_FONT_MINI: + uifont = kCTFontMiniSystemFontType; + break; + case wxOSX_SYSTEM_FONT_MINI_BOLD: + uifont = kCTFontMiniEmphasizedSystemFontType; + break; + case wxOSX_SYSTEM_FONT_LABELS: + uifont = kCTFontLabelFontType; + break; + case wxOSX_SYSTEM_FONT_VIEWS: + uifont = kCTFontViewsFontType; + break; + default: + break; + } + wxCFRef ctfont(CTFontCreateUIFontForLanguage(uifont, 0.0, NULL)); + m_refData = new wxFontRefData(ctfont); +} + +wxFont::wxFont(WX_NSFont nsfont) +{ + m_refData = new wxFontRefData((CTFontRef)nsfont); +} + +wxFont::wxFont(CTFontRef font) +{ + m_refData = new wxFontRefData(font); } wxFont::wxFont(const wxString& fontdesc) { wxNativeFontInfo info; - if ( info.FromString(fontdesc) ) + if (info.FromString(fontdesc)) (void)Create(info); } wxFont::wxFont(int size, - int family, - int style, - int weight, - bool underlined, - const wxString& face, - wxFontEncoding encoding) + int family, + int style, + int weight, + bool underlined, + const wxString& face, + wxFontEncoding encoding) { (void)Create(size, (wxFontFamily)family, (wxFontStyle)style, - (wxFontWeight)weight, underlined, face, encoding); + (wxFontWeight)weight, underlined, face, encoding); +} + +bool wxFont::Create(float pointSize, + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, + bool underlined, + const wxString& faceName, + wxFontEncoding encoding) +{ + UnRef(); + + m_refData = new wxFontRefData(pointSize, family, style, weight, + underlined, false, faceName, encoding); + + return true; } bool wxFont::Create(int pointSize, - wxFontFamily family, - wxFontStyle style, - wxFontWeight weight, - bool underlined, - const wxString& faceNameParam, - wxFontEncoding encoding) + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, + bool underlined, + const wxString& faceName, + wxFontEncoding encoding) { - UnRef(); + // wxDEFAULT is a valid value for the font size too so we must treat it + // specially here (otherwise the size would be 70 == wxDEFAULT value) + if (pointSize == wxDEFAULT) + pointSize = -1; - wxString faceName = faceNameParam; - - if ( faceName.empty() ) - { - switch ( family ) - { - case wxFONTFAMILY_DEFAULT : - faceName = wxT("Lucida Grande"); - break; - - case wxFONTFAMILY_SCRIPT : - case wxFONTFAMILY_ROMAN : - case wxFONTFAMILY_DECORATIVE : - faceName = wxT("Times"); - break ; - - case wxFONTFAMILY_SWISS : - faceName = wxT("Helvetica"); - break ; - - case wxFONTFAMILY_MODERN : - case wxFONTFAMILY_TELETYPE: - faceName = wxT("Courier"); - break ; - - default: - faceName = wxT("Times"); - break ; - } - } - - wxNativeFontInfo info; - - info.Init(pointSize, family, style, weight, - underlined, false, faceName, encoding); - - m_refData = new wxFontRefData(info); - - return true; + return Create((float)pointSize, family, style, weight, underlined, faceName, encoding); } wxFont::~wxFont() @@ -479,70 +602,74 @@ void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info) { UnRef(); - m_refData = new wxFontRefData( info); + m_refData = new wxFontRefData(info); } - bool wxFont::RealizeResource() { - M_FONTDATA->MacFindFont(); - - return true; + return OSXGetCTFont(); } void wxFont::SetEncoding(wxFontEncoding encoding) { AllocExclusive(); - M_FONTDATA->SetEncoding( encoding ); + M_FONTDATA->SetEncoding(encoding); } -wxGDIRefData *wxFont::CreateGDIRefData() const +wxGDIRefData* wxFont::CreateGDIRefData() const { return new wxFontRefData; } -wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const +wxGDIRefData* wxFont::CloneGDIRefData(const wxGDIRefData* data) const { - return new wxFontRefData(*static_cast(data)); + return new wxFontRefData(*static_cast(data)); } -void wxFont::SetPointSize(int pointSize) +void wxFont::SetPointSize(float pointSize) { - if ( M_FONTDATA != NULL && M_FONTDATA->GetPointSize() == pointSize ) + if (IsOk() && M_FONTDATA->GetFractionalPointSize() == pointSize) return; AllocExclusive(); - M_FONTDATA->SetPointSize( pointSize ); + M_FONTDATA->SetPointSize(pointSize); } void wxFont::SetFamily(wxFontFamily family) { AllocExclusive(); - M_FONTDATA->SetFamily( family ); + M_FONTDATA->SetFamily(family); } void wxFont::SetStyle(wxFontStyle style) { AllocExclusive(); - M_FONTDATA->SetStyle( style ); + M_FONTDATA->SetStyle(style); } void wxFont::SetWeight(wxFontWeight weight) { AllocExclusive(); - M_FONTDATA->SetWeight( weight ); + M_FONTDATA->SetWeight(weight); +} + +void wxFont::SetNumericWeight(int weight) +{ + AllocExclusive(); + + M_FONTDATA->SetNumericWeight(weight); } bool wxFont::SetFaceName(const wxString& faceName) { AllocExclusive(); - M_FONTDATA->SetFaceName( faceName ); + M_FONTDATA->SetFaceName(faceName); return wxFontBase::SetFaceName(faceName); } @@ -551,14 +678,14 @@ void wxFont::SetUnderlined(bool underlined) { AllocExclusive(); - M_FONTDATA->SetUnderlined( underlined ); + M_FONTDATA->SetUnderlined(underlined); } void wxFont::SetStrikethrough(bool strikethrough) { - AllocExclusive(); + AllocExclusive(); - M_FONTDATA->SetStrikethrough( strikethrough ); + M_FONTDATA->SetStrikethrough(strikethrough); } // ---------------------------------------------------------------------------- @@ -567,21 +694,21 @@ void wxFont::SetStrikethrough(bool strikethrough) // TODO: insert checks everywhere for M_FONTDATA == NULL! -int wxFont::GetPointSize() const +float wxFont::GetFractionalPointSize() const { - wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); + wxCHECK_MSG(IsOk(), 0, wxT("invalid font")); - return M_FONTDATA->GetPointSize(); + return M_FONTDATA->GetFractionalPointSize(); } wxSize wxFont::GetPixelSize() const { #if wxUSE_GRAPHICS_CONTEXT // TODO: consider caching the value - wxGraphicsContext* dc = wxGraphicsContext::CreateFromNative((CGContextRef) NULL); - dc->SetFont(*(wxFont *)this,*wxBLACK); + wxGraphicsContext* dc = wxGraphicsContext::CreateFromNative((CGContextRef)NULL); + dc->SetFont(*(wxFont*)this, *wxBLACK); wxDouble width, height = 0; - dc->GetTextExtent( wxT("g"), &width, &height, NULL, NULL); + dc->GetTextExtent(wxT("g"), &width, &height, NULL, NULL); delete dc; return wxSize((int)width, (int)height); #else @@ -591,10 +718,10 @@ wxSize wxFont::GetPixelSize() const bool wxFont::IsFixedWidth() const { - wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") ); - + wxCHECK_MSG(IsOk(), false, wxT("invalid font")); + // cast away constness otherwise lazy font resolution is not possible - const_cast(this)->RealizeResource(); + const_cast(this)->RealizeResource(); return M_FONTDATA->IsFixedWidth(); } @@ -606,91 +733,78 @@ wxFontFamily wxFont::DoGetFamily() const wxFontStyle wxFont::GetStyle() const { - wxCHECK_MSG( M_FONTDATA != NULL , wxFONTSTYLE_MAX, wxT("invalid font") ); + wxCHECK_MSG(IsOk(), wxFONTSTYLE_MAX, wxT("invalid font")); - return M_FONTDATA->GetStyle() ; + return M_FONTDATA->GetStyle(); } wxFontWeight wxFont::GetWeight() const { - wxCHECK_MSG( M_FONTDATA != NULL , wxFONTWEIGHT_MAX, wxT("invalid font") ); + wxCHECK_MSG(IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font")); return M_FONTDATA->GetWeight(); } +int wxFont::GetNumericWeight() const +{ + wxCHECK_MSG(IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font")); + + return M_FONTDATA->GetNumericWeight(); +} + bool wxFont::GetUnderlined() const { - wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") ); + wxCHECK_MSG(IsOk(), false, wxT("invalid font")); return M_FONTDATA->GetUnderlined(); } bool wxFont::GetStrikethrough() const { - wxCHECK_MSG( M_FONTDATA != NULL, false, wxT("invalid font") ); + wxCHECK_MSG(IsOk(), false, wxT("invalid font")); return M_FONTDATA->GetStrikethrough(); } wxString wxFont::GetFaceName() const { - wxCHECK_MSG( M_FONTDATA != NULL , wxEmptyString , wxT("invalid font") ); + wxCHECK_MSG(IsOk(), wxEmptyString, wxT("invalid font")); - return M_FONTDATA->GetFaceName() ; + return M_FONTDATA->GetFaceName(); } wxFontEncoding wxFont::GetEncoding() const { - wxCHECK_MSG( M_FONTDATA != NULL , wxFONTENCODING_DEFAULT , wxT("invalid font") ); + wxCHECK_MSG(IsOk(), wxFONTENCODING_DEFAULT, wxT("invalid font")); - return M_FONTDATA->GetEncoding() ; + return M_FONTDATA->GetEncoding(); } CTFontRef wxFont::OSXGetCTFont() const { - wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); - - // cast away constness otherwise lazy font resolution is not possible - const_cast(this)->RealizeResource(); - - return (CTFontRef)(M_FONTDATA->m_ctFont); + wxCHECK_MSG(IsOk(), 0, wxT("invalid font")); + return M_FONTDATA->OSXGetCTFont(); } CFDictionaryRef wxFont::OSXGetCTFontAttributes() const { - wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") ); - - // cast away constness otherwise lazy font resolution is not possible - const_cast(this)->RealizeResource(); - - return (CFDictionaryRef)(M_FONTDATA->m_ctFontAttributes); + wxCHECK_MSG(IsOk(), 0, wxT("invalid font")); + return M_FONTDATA->OSXGetCTFontAttributes(); } #if wxOSX_USE_COCOA_OR_CARBON CGFontRef wxFont::OSXGetCGFont() const { - wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); - - // cast away constness otherwise lazy font resolution is not possible - const_cast(this)->RealizeResource(); - - return (M_FONTDATA->m_cgFont); + wxCHECK_MSG(IsOk(), 0, wxT("invalid font")); + return M_FONTDATA->OSXGetCGFont(); } #endif -const wxNativeFontInfo * wxFont::GetNativeFontInfo() const +const wxNativeFontInfo* wxFont::GetNativeFontInfo() const { - wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") ); - wxCHECK_MSG( IsOk(), NULL, wxT("invalid font") ); - - // cast away constness otherwise lazy font resolution is not possible - const_cast(this)->RealizeResource(); - - // M_FONTDATA->m_info.InitFromFont(*this); - - return &(M_FONTDATA->m_info); + return IsOk() ? &(M_FONTDATA->GetNativeFontInfo()) : NULL; } // ---------------------------------------------------------------------------- @@ -699,149 +813,169 @@ const wxNativeFontInfo * wxFont::GetNativeFontInfo() const /* from Core Text Manual Common Operations */ -static CTFontDescriptorRef wxMacCreateCTFontDescriptor(CFStringRef iFamilyName, CTFontSymbolicTraits iTraits ) -{ - CTFontDescriptorRef descriptor = NULL; - CFMutableDictionaryRef attributes; - - wxASSERT(iFamilyName != NULL); - // Create a mutable dictionary to hold our attributes. - attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - wxASSERT(attributes != NULL); - - if (attributes != NULL) { - // Add a family name to our attributes. - CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, iFamilyName); - - - if ( iTraits ) { - CFMutableDictionaryRef traits; - CFNumberRef symTraits; - - // Create the traits dictionary. - symTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, - &iTraits); - wxASSERT(symTraits != NULL); - - if (symTraits != NULL) { - // Create a dictionary to hold our traits values. - traits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - wxASSERT(traits != NULL); - - if (traits != NULL) { - // Add the symbolic traits value to the traits dictionary. - CFDictionaryAddValue(traits, kCTFontSymbolicTrait, symTraits); - - // Add the traits attribute to our attributes. - CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits); - CFRelease(traits); - } - CFRelease(symTraits); - } - } - // Create the font descriptor with our attributes - descriptor = CTFontDescriptorCreateWithAttributes(attributes); - wxASSERT(descriptor != NULL); - - CFRelease(attributes); - } - // Return our font descriptor. - return descriptor ; -} - - void wxNativeFontInfo::Init() { - m_pointSize = 0; - m_family = wxFONTFAMILY_DEFAULT; - m_style = wxFONTSTYLE_NORMAL; - m_weight = wxFONTWEIGHT_NORMAL; + m_descriptor.reset(); + m_underlined = false; m_strikethrough = false; - m_faceName.clear(); - m_encoding = wxFont::GetDefaultEncoding(); -} + m_encoding = wxFONTENCODING_UTF8; -void wxNativeFontInfo::Init(CTFontDescriptorRef descr) -{ - Init(); + m_ctWeight = 0.0; + m_style = wxFONTSTYLE_NORMAL; + m_ctSize = 0.0; + m_family = wxFONTFAMILY_DEFAULT; - wxCFRef< CFNumberRef > sizevalue( (CFNumberRef) CTFontDescriptorCopyAttribute( descr, kCTFontSizeAttribute ) ); - float fsize; - if ( CFNumberGetValue( sizevalue , kCFNumberFloatType , &fsize ) ) - m_pointSize = (int)( fsize + 0.5 ); - - wxCFRef< CFDictionaryRef > traitsvalue( (CFDictionaryRef) CTFontDescriptorCopyAttribute( descr, kCTFontTraitsAttribute ) ); - CTFontSymbolicTraits traits; - if ( CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(traitsvalue,kCTFontSymbolicTrait),kCFNumberIntType,&traits) ) - { - if ( traits & kCTFontItalicTrait ) - m_style = wxFONTSTYLE_ITALIC; - if ( traits & kCTFontBoldTrait ) - m_weight = wxFONTWEIGHT_BOLD ; - } - - wxCFStringRef familyName( (CFStringRef) CTFontDescriptorCopyAttribute(descr, kCTFontFamilyNameAttribute)); - m_faceName = familyName.AsString(); - - UpdateNamesMap(m_faceName, descr); + m_styleName.clear(); + m_familyName.clear(); } void wxNativeFontInfo::Init(const wxNativeFontInfo& info) { Init(); - m_pointSize = info.m_pointSize; - m_family = info.m_family; - m_style = info.m_style; - m_weight = info.m_weight; + + m_descriptor = info.m_descriptor; + m_underlined = info.m_underlined; m_strikethrough = info.m_strikethrough; - m_faceName = info.m_faceName; m_encoding = info.m_encoding; + + m_ctWeight = info.m_ctWeight; + m_style = info.m_style; + m_ctSize = info.m_ctSize; + m_family = info.m_family; + + m_styleName = info.m_styleName; + m_familyName = info.m_familyName; } -void wxNativeFontInfo::Init(int size, - wxFontFamily family, - wxFontStyle style, - wxFontWeight weight, - bool underlined, - bool strikethrough, - const wxString& faceName, - wxFontEncoding encoding) +void wxNativeFontInfo::InitFromFont(CTFontRef font) { Init(); - // We should use the default font size if the special value wxDEFAULT is - // specified and we also handle -1 as a synonym for wxDEFAULT for - // compatibility with wxGTK (see #12541). - // - // Notice that we rely on the fact that wxNORMAL_FONT itself is not - // initialized using this ctor, but from native font info. - m_pointSize = size == -1 || size == wxDEFAULT - ? wxNORMAL_FONT->GetPointSize() - : size; - m_family = family; - m_style = style; - m_weight = weight; - m_underlined = underlined; - m_strikethrough = strikethrough; - m_faceName = faceName; - if ( encoding == wxFONTENCODING_DEFAULT ) - encoding = wxFont::GetDefaultEncoding(); - m_encoding = encoding; + InitFromFontDescriptor(CTFontCopyFontDescriptor(font) ); +} +void wxNativeFontInfo::InitFromFontDescriptor(CTFontDescriptorRef desc) +{ + Init(); + + m_descriptor.reset(wxCFRetain(desc)); + + m_ctWeight = GetCTWeight(desc); + m_style = GetCTSlant(desc) > 0.01 ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL; + wxCFTypeRef(CTFontDescriptorCopyAttribute(desc, kCTFontSizeAttribute)).GetValue(m_ctSize, 0.0); + + // determine approximate family + + CTFontSymbolicTraits symbolicTraits; + wxCFDictionaryRef traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(desc, kCTFontTraitsAttribute)); + traits.GetValue(kCTFontSymbolicTrait).GetValue((int32_t*)&symbolicTraits, 0); + + m_family = wxFONTFAMILY_DEFAULT; + + if (symbolicTraits & kCTFontTraitMonoSpace) + m_family = wxFONTFAMILY_TELETYPE; + else + { + uint32_t stylisticClass = symbolicTraits & kCTFontTraitClassMask; + + if (stylisticClass == kCTFontSansSerifClass) + m_family = wxFONTFAMILY_SWISS; + else if (stylisticClass == kCTFontScriptsClass) + m_family = wxFONTFAMILY_SCRIPT; + else if (stylisticClass == kCTFontOrnamentalsClass) + m_family = wxFONTFAMILY_DECORATIVE; + else if (stylisticClass == kCTFontSymbolicClass) + m_family = wxFONTFAMILY_DECORATIVE; + else + m_family = wxFONTFAMILY_ROMAN; + } + + wxCFTypeRef(CTFontDescriptorCopyAttribute(desc, kCTFontStyleNameAttribute)).GetValue(m_styleName); + wxCFTypeRef(CTFontDescriptorCopyAttribute(desc, kCTFontFamilyNameAttribute)).GetValue(m_familyName); } void wxNativeFontInfo::Free() { + m_descriptor.reset(); } +CTFontDescriptorRef wxNativeFontInfo::GetCTFontDescriptor() const +{ + if ( !m_descriptor ) + const_cast(this)->CreateCTFontDescriptor(); + + return m_descriptor; +} + +void wxNativeFontInfo::CreateCTFontDescriptor() +{ + CTFontDescriptorRef descriptor = NULL; + wxCFMutableDictionaryRef attributes; + + // build all attributes that define our font. + + wxString fontfamilyname = m_familyName; + if ( fontfamilyname.empty() ) + fontfamilyname = FamilyToFaceName(m_family); + + + CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, wxCFStringRef(fontfamilyname)); + + wxCFMutableDictionaryRef traits; + if ( m_style != wxFONTSTYLE_NORMAL ) + traits.SetValue(kCTFontSymbolicTrait, kCTFontItalicTrait); + + traits.SetValue(kCTFontWeightTrait,m_ctWeight); + + attributes.SetValue(kCTFontTraitsAttribute,traits.get()); + attributes.SetValue(kCTFontSizeAttribute, m_ctSize); + + // Create the font descriptor with our attributes + descriptor = CTFontDescriptorCreateWithAttributes(attributes); + wxASSERT(descriptor != NULL); + + m_descriptor = descriptor; +} + +// Core Text Helpers + +CGFloat wxNativeFontInfo::GetCTWeight(CTFontRef font) +{ + CGFloat weight; + CFTypeRef fonttraitstype = CTFontCopyAttribute(font, kCTFontTraitsAttribute); + wxCFDictionaryRef traits((CFDictionaryRef)fonttraitstype); + traits.GetValue(kCTFontWeightTrait).GetValue(&weight, 0.0); + return weight; +} + +CGFloat wxNativeFontInfo::GetCTWeight(CTFontDescriptorRef descr) +{ + CGFloat weight; + CFTypeRef fonttraitstype = CTFontDescriptorCopyAttribute(descr, kCTFontTraitsAttribute); + wxCFDictionaryRef traits((CFDictionaryRef)fonttraitstype); + traits.GetValue(kCTFontWeightTrait).GetValue(&weight, 0.0); + return weight; +} + +CGFloat wxNativeFontInfo::GetCTSlant(CTFontDescriptorRef descr) +{ + CGFloat slant; + CFTypeRef fonttraitstype = CTFontDescriptorCopyAttribute(descr, kCTFontTraitsAttribute); + wxCFDictionaryRef traits((CFDictionaryRef)fonttraitstype); + traits.GetValue(kCTFontSlantTrait).GetValue(&slant, 0.0); + return slant; +} + + +// bool wxNativeFontInfo::FromString(const wxString& s) { long l, version; + Init(); + wxStringTokenizer tokenizer(s, wxT(";")); wxString token = tokenizer.GetNextToken(); @@ -855,7 +989,7 @@ bool wxNativeFontInfo::FromString(const wxString& s) token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) return false; - m_pointSize = (int)l; + m_ctSize = (int)l; token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) @@ -870,7 +1004,7 @@ bool wxNativeFontInfo::FromString(const wxString& s) token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) return false; - m_weight = (wxFontWeight)l; + m_ctWeight = WXWeightToCT(l); token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) @@ -889,10 +1023,10 @@ bool wxNativeFontInfo::FromString(const wxString& s) m_strikethrough = l != 0; } - m_faceName = tokenizer.GetNextToken(); + m_familyName = tokenizer.GetNextToken(); #ifndef __WXMAC__ - if( !faceName ) + if( !m_familyName ) return false; #endif @@ -909,22 +1043,27 @@ wxString wxNativeFontInfo::ToString() const wxString s; s.Printf(wxT("%d;%d;%d;%d;%d;%d;%d;%s;%d"), - 1, // version - m_pointSize, - m_family, - (int)m_style, - (int)m_weight, - m_underlined, - m_strikethrough, - m_faceName.GetData(), - (int)m_encoding); + 1, // version + GetPointSize(), + GetFamily(), + (int)GetStyle(), + (int)GetWeight(), + GetUnderlined(), + GetStrikethrough(), + GetFaceName().GetData(), + (int)GetEncoding()); return s; } int wxNativeFontInfo::GetPointSize() const { - return m_pointSize; + return wxRound(GetFractionalPointSize()); +} + +float wxNativeFontInfo::GetFractionalPointSize() const +{ + return m_ctSize; } wxFontStyle wxNativeFontInfo::GetStyle() const @@ -932,9 +1071,9 @@ wxFontStyle wxNativeFontInfo::GetStyle() const return m_style; } -wxFontWeight wxNativeFontInfo::GetWeight() const +int wxNativeFontInfo::GetNumericWeight() const { - return m_weight; + return CTWeightToWX(m_ctWeight /* GetCTWeight(m_descriptor)*/); } bool wxNativeFontInfo::GetUnderlined() const @@ -942,9 +1081,47 @@ bool wxNativeFontInfo::GetUnderlined() const return m_underlined; } +wxString wxNativeFontInfo::GetFamilyName() const +{ + return m_familyName; +} + +wxString wxNativeFontInfo::GetStyleName() const +{ + return m_styleName; +} + wxString wxNativeFontInfo::GetFaceName() const { - return m_faceName; +#if wxDEBUG_LEVEL >= 2 + // for debugging: show all different font names + wxCFRef font = CTFontCreateWithFontDescriptor(m_descriptor, 12, NULL); + wxString familyname; + wxCFTypeRef(CTFontDescriptorCopyAttribute(m_descriptor, kCTFontFamilyNameAttribute)).GetValue(familyname); + wxLogTrace(TRACE_CTFONT,"FontFamilyName: %s",familyname.c_str()); + + wxString name; + wxCFTypeRef(CTFontDescriptorCopyAttribute(m_descriptor, kCTFontNameAttribute)).GetValue(name); + wxLogTrace(TRACE_CTFONT,"FontName: %s",name.c_str()); + + wxString psname; + wxCFTypeRef(CTFontCopyPostScriptName(font)).GetValue(psname); + wxLogTrace(TRACE_CTFONT,"PostScriptName: %s",psname.c_str()); + + wxString fullname; + wxCFTypeRef(CTFontCopyFullName(font)).GetValue(fullname); + wxLogTrace(TRACE_CTFONT,"FullName: %s",fullname.c_str()); + + wxString display; + wxCFTypeRef(CTFontDescriptorCopyAttribute(m_descriptor, kCTFontDisplayNameAttribute)).GetValue(display); + wxLogTrace(TRACE_CTFONT,"DisplayName: %s",display.c_str()); + + wxString style; + wxCFTypeRef(CTFontDescriptorCopyAttribute(m_descriptor, kCTFontStyleNameAttribute)).GetValue(style); + wxLogTrace(TRACE_CTFONT,"StyleName: %s",style.c_str()); +#endif + + return m_familyName; } wxFontFamily wxNativeFontInfo::GetFamily() const @@ -962,70 +1139,72 @@ bool wxNativeFontInfo::GetStrikethrough() const return m_strikethrough; } - // changing the font descriptor -void wxNativeFontInfo::SetPointSize(int pointsize) +void wxNativeFontInfo::SetPointSize(float pointsize) { - if ( m_pointSize != pointsize ) + if (GetPointSize() != pointsize) { - m_pointSize = pointsize; - Free(); + m_ctSize = pointsize; + + if ( m_descriptor) + { + wxCFMutableDictionaryRef attributes; + attributes.SetValue(kCTFontSizeAttribute, wxCFNumberRef((CGFloat)pointsize)); + m_descriptor.reset(CTFontDescriptorCreateCopyWithAttributes(m_descriptor, attributes)); + } } } void wxNativeFontInfo::SetStyle(wxFontStyle style_) { - if ( m_style != style_ ) + bool formerIsItalic = GetStyle() != wxFONTSTYLE_NORMAL; + bool newIsItalic = style_ != wxFONTSTYLE_NORMAL; + + m_style = style_; + + if (formerIsItalic != newIsItalic) { - m_style = style_; Free(); } } -void wxNativeFontInfo::SetWeight(wxFontWeight weight_) +void wxNativeFontInfo::SetNumericWeight(int weight) { - if ( m_weight != weight_ ) + int formerWeight = GetNumericWeight(); + if (formerWeight != weight) { - m_weight = weight_; Free(); + m_ctWeight = WXWeightToCT(weight); } } -void wxNativeFontInfo::SetUnderlined(bool underlined_) +void wxNativeFontInfo::SetUnderlined(bool underlined) { - if ( m_underlined != underlined_ ) - { - m_underlined = underlined_; - Free(); - } + m_underlined = underlined; } -bool wxNativeFontInfo::SetFaceName(const wxString& facename_) +bool wxNativeFontInfo::SetFaceName(const wxString& facename) { - if ( m_faceName != facename_ ) + if (GetFaceName() != facename) { - m_faceName = facename_; Free(); + m_familyName = facename; } + return true; } -void wxNativeFontInfo::SetFamily(wxFontFamily family_) +void wxNativeFontInfo::SetFamily(wxFontFamily family) { - if ( m_family != family_ ) - { - m_family = family_; - Free(); - } + Free(); + m_familyName.clear(); + m_family = family; } -void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_) +void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding) { - if ( encoding_ == wxFONTENCODING_DEFAULT ) - encoding_ = wxFont::GetDefaultEncoding(); - m_encoding = encoding_; - // not reflected in native descriptors + wxUnusedVar(encoding); } void wxNativeFontInfo::SetStrikethrough(bool strikethrough) @@ -1035,21 +1214,20 @@ void wxNativeFontInfo::SetStrikethrough(bool strikethrough) void wxNativeFontInfo::UpdateNamesMap(const wxString& familyName, CTFontDescriptorRef descr) { - if ( gs_FontFamilyToPSName.find(familyName) == gs_FontFamilyToPSName.end() ) + if (gs_FontFamilyToPSName.find(familyName) == gs_FontFamilyToPSName.end()) { - wxCFStringRef psName( (CFStringRef) CTFontDescriptorCopyAttribute(descr, kCTFontNameAttribute)); + wxCFStringRef psName((CFStringRef)CTFontDescriptorCopyAttribute(descr, kCTFontNameAttribute)); gs_FontFamilyToPSName[familyName] = psName.AsString(); } } void wxNativeFontInfo::UpdateNamesMap(const wxString& familyName, CTFontRef font) { - if ( gs_FontFamilyToPSName.find(familyName) == gs_FontFamilyToPSName.end() ) + if (gs_FontFamilyToPSName.find(familyName) == gs_FontFamilyToPSName.end()) { - wxCFRef descr(CTFontCopyFontDescriptor( font )); + wxCFRef descr(CTFontCopyFontDescriptor(font)); UpdateNamesMap(familyName, descr); } } - diff --git a/src/osx/carbon/fontdlgosx.mm b/src/osx/carbon/fontdlgosx.mm index b61908f0c4..1e6f804476 100644 --- a/src/osx/carbon/fontdlgosx.mm +++ b/src/osx/carbon/fontdlgosx.mm @@ -274,7 +274,8 @@ int RunMixedFontDialog(wxFontDialog* dialog) if ( [accessoryView closedWithOk]) { #if wxOSX_USE_COCOA - fontdata.m_chosenFont = wxFont( theFont ); + fontdata.m_chosenFont = wxFont(theFont); + // copy the attributes not contained in a native CTFont fontdata.m_chosenFont.SetUnderlined(theFPDelegate->m_isUnderline); fontdata.m_chosenFont.SetStrikethrough(theFPDelegate->m_isStrikethrough); @@ -456,31 +457,11 @@ bool wxFontDialog::Create(wxWindow *parent) //NSFontDialog to that font if (thewxfont.IsOk()) { - NSFontTraitMask theMask = 0; - - if(thewxfont.GetStyle() == wxFONTSTYLE_ITALIC) - theMask |= NSItalicFontMask; - - if(thewxfont.IsFixedWidth()) - theMask |= NSFixedPitchFontMask; - - NSFont* theDefaultFont = - [[NSFontManager sharedFontManager] fontWithFamily: - wxNSStringWithWxString(thewxfont.GetFaceName()) - traits:theMask - weight:thewxfont.GetWeight() == wxFONTWEIGHT_BOLD ? 9 : - thewxfont.GetWeight() == wxFONTWEIGHT_LIGHT ? 0 : 5 - size: (float)(thewxfont.GetPointSize()) - ]; - - wxASSERT_MSG(theDefaultFont, wxT("Invalid default font for wxCocoaFontDialog!")); - //Apple docs say to call NSFontManager::setSelectedFont //However, 10.3 doesn't seem to create the font panel //is this is done, so create it ourselves - [[NSFontPanel sharedFontPanel] setPanelFont:theDefaultFont isMultiple:NO]; + [[NSFontPanel sharedFontPanel] setPanelFont:thewxfont.OSXGetNSFont() isMultiple:NO]; [[NSFontManager sharedFontManager] setSelectedFont:theDefaultFont isMultiple:false]; - } if(m_fontData.m_fontColour.IsOk()) @@ -579,22 +560,11 @@ int wxFontDialog::ShowModal() //Get the font the user selected NSFont* theFont = [theFontPanel panelConvertFont:[NSFont userFontOfSize:0]]; - - //Get more information about the user's chosen font - NSFontTraitMask theTraits = [[NSFontManager sharedFontManager] traitsOfFont:theFont]; - int theFontWeight = [[NSFontManager sharedFontManager] weightOfFont:theFont]; - int theFontSize = (int) [theFont pointSize]; - - //Set the wx font to the appropriate data - if(theTraits & NSFixedPitchFontMask) - m_fontData.m_chosenFont.SetFamily(wxTELETYPE); - - m_fontData.m_chosenFont.SetFaceName(wxStringWithNSString([theFont familyName])); - m_fontData.m_chosenFont.SetPointSize(theFontSize); - m_fontData.m_chosenFont.SetStyle(theTraits & NSItalicFontMask ? wxFONTSTYLE_ITALIC : 0); - m_fontData.m_chosenFont.SetWeight(theFontWeight < 5 ? wxFONTWEIGHT_LIGHT : - theFontWeight >= 9 ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL); - + m_fontData.m_chosenFont = wxFont(theFont); + // copy the attributes not contained in a native CTFont + m_fontData.m_chosenFont.SetUnderlined(theFPDelegate->m_isUnderline); + m_fontData.m_chosenFont.SetStrikethrough(theFPDelegate->m_isStrikethrough); + //Get the shared color panel along with the chosen color and set the chosen color m_fontData.m_fontColour = wxColour([theColorPanel color]); diff --git a/src/osx/carbon/graphics.cpp b/src/osx/carbon/graphics.cpp index 5569691a93..ec1b9643bb 100644 --- a/src/osx/carbon/graphics.cpp +++ b/src/osx/carbon/graphics.cpp @@ -834,10 +834,10 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere m_underlined = font.GetUnderlined(); m_strikethrough = font.GetStrikethrough(); - m_ctFont.reset( wxCFRetain( font.OSXGetCTFont() ) ); - m_ctFontAttributes.reset( wxCFRetain( font.OSXGetCTFontAttributes() ) ); + m_ctFont = wxCFRetain(font.OSXGetCTFont()); + m_ctFontAttributes = wxCFRetain(font.OSXGetCTFontAttributes()); #if wxOSX_USE_IPHONE - m_uiFont.reset( wxCFRetain( font.OSXGetUIFont() ) ); + m_uiFont = font.OSXGetUIFont(); #endif } @@ -2892,13 +2892,10 @@ wxMacCoreGraphicsRenderer::CreateFont(double sizeInPixels, int flags, const wxColour& col) { - // This implementation is not ideal as we don't support fractional font - // sizes right now, but it's the simplest one. - // // Notice that under Mac we always use 72 DPI so the font size in pixels is // the same as the font size in points and we can pass it directly to wxFont // ctor. - wxFont font(wxRound(sizeInPixels), + wxFont font((float)sizeInPixels, wxFONTFAMILY_DEFAULT, flags & wxFONTFLAG_ITALIC ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL, diff --git a/src/osx/carbon/utilscocoa.mm b/src/osx/carbon/utilscocoa.mm index a492649cb2..67c2f6ed3b 100644 --- a/src/osx/carbon/utilscocoa.mm +++ b/src/osx/carbon/utilscocoa.mm @@ -97,48 +97,6 @@ void* wxMacCocoaRetain( void* obj ) // ---------------------------------------------------------------------------- #if wxOSX_USE_COCOA -wxFont::wxFont(WX_NSFont nsfont) -{ - wxNativeFontInfo info; - SetNativeInfoFromNSFont(nsfont, &info); - Create(info); -} - -void wxFont::SetNativeInfoFromNSFont(WX_NSFont theFont, wxNativeFontInfo* info) -{ - if ( info->m_faceName.empty()) - { - //Get more information about the user's chosen font - NSFontTraitMask theTraits = [[NSFontManager sharedFontManager] traitsOfFont:theFont]; - int theFontWeight = [[NSFontManager sharedFontManager] weightOfFont:theFont]; - - wxFontFamily fontFamily = wxFONTFAMILY_DEFAULT; - //Set the wx font to the appropriate data - if(theTraits & NSFixedPitchFontMask) - fontFamily = wxFONTFAMILY_TELETYPE; - - wxFontStyle fontstyle = wxFONTSTYLE_NORMAL; - wxFontWeight fontweight = wxFONTWEIGHT_NORMAL; - bool underlined = false; - bool strikethrough = false; - - int size = (int) ([theFont pointSize]+0.5); - - if ( theFontWeight >= 9 ) - fontweight = wxFONTWEIGHT_BOLD ; - else if ( theFontWeight < 5 ) - fontweight = wxFONTWEIGHT_LIGHT; - else - fontweight = wxFONTWEIGHT_NORMAL ; - - if ( theTraits & NSItalicFontMask ) - fontstyle = wxFONTSTYLE_ITALIC ; - - info->Init(size,fontFamily,fontstyle,fontweight,underlined, strikethrough, - wxCFStringRef::AsString([theFont familyName]), wxFONTENCODING_DEFAULT); - - } -} NSFont* wxFont::OSXGetNSFont() const { @@ -597,8 +555,6 @@ wxOSXEffectiveAppearanceSetter::wxOSXEffectiveAppearanceSetter() formerAppearance = NSAppearance.currentAppearance; NSAppearance.currentAppearance = NSApp.effectiveAppearance; } -#else - wxUnusedVar(formerAppearance); #endif } diff --git a/src/propgrid/advprops.cpp b/src/propgrid/advprops.cpp index 0aa2e03cc8..b18e0ad834 100644 --- a/src/propgrid/advprops.cpp +++ b/src/propgrid/advprops.cpp @@ -617,16 +617,30 @@ static const long gs_fp_es_style_values[] = { }; static const wxChar* const gs_fp_es_weight_labels[] = { - wxT("Normal"), + wxT("Thin"), + wxT("ExtraLight"), wxT("Light"), + wxT("Normal"), + wxT("Medium"), + wxT("SemiBold"), wxT("Bold"), + wxT("ExtraBold"), + wxT("Heavy"), + wxT("ExtraHeavy"), (const wxChar*) NULL }; static const long gs_fp_es_weight_values[] = { - wxFONTWEIGHT_NORMAL, + wxFONTWEIGHT_THIN, + wxFONTWEIGHT_EXTRALIGHT, wxFONTWEIGHT_LIGHT, - wxFONTWEIGHT_BOLD + wxFONTWEIGHT_NORMAL, + wxFONTWEIGHT_MEDIUM, + wxFONTWEIGHT_SEMIBOLD, + wxFONTWEIGHT_BOLD, + wxFONTWEIGHT_EXTRABOLD, + wxFONTWEIGHT_HEAVY, + wxFONTWEIGHT_EXTRAHEAVY }; // Class body is in advprops.h @@ -788,9 +802,7 @@ wxVariant wxFontProperty::ChildChanged( wxVariant& thisValue, else if ( ind == 3 ) { int wt = childValue.GetLong(); - if ( wt != wxFONTWEIGHT_NORMAL && - wt != wxFONTWEIGHT_LIGHT && - wt != wxFONTWEIGHT_BOLD ) + if ( wt < wxFONTWEIGHT_THIN || wt > wxFONTWEIGHT_MAX ) wt = wxFONTWEIGHT_NORMAL; font.SetWeight( static_cast(wt) ); } diff --git a/src/qt/font.cpp b/src/qt/font.cpp index f9d5525d4a..cd01b207ec 100644 --- a/src/qt/font.cpp +++ b/src/qt/font.cpp @@ -53,7 +53,7 @@ static QFont::StyleHint ConvertFontFamily(wxFontFamily family) return QFont::AnyStyle; } -static QFont::Weight ConvertFontWeight(wxFontWeight weight) +static QFont::Weight ConvertFontWeight(int weight) { switch (weight) { @@ -66,6 +66,12 @@ static QFont::Weight ConvertFontWeight(wxFontWeight weight) case wxFONTWEIGHT_BOLD: return QFont::Bold; + case wxFONTWEIGHT_SEMIBOLD: + return QFont::DemiBold; + + case wxFONTWEIGHT_HEAVY: + return QFont::Black; + case wxFONTWEIGHT_MAX: wxFAIL_MSG( "Invalid font weight value" ); break; @@ -328,7 +334,7 @@ wxFontStyle wxNativeFontInfo::GetStyle() const return wxFontStyle(); } -wxFontWeight wxNativeFontInfo::GetWeight() const +int wxNativeFontInfo::GetNumericWeight() const { switch ( m_qtFont.weight() ) { @@ -339,12 +345,16 @@ wxFontWeight wxNativeFontInfo::GetWeight() const return wxFONTWEIGHT_LIGHT; case QFont::DemiBold: + return wxFONTWEIGHT_SEMIBOLD; + case QFont::Black: + return wxFONTWEIGHT_HEAVY; + case QFont::Bold: return wxFONTWEIGHT_BOLD; } wxFAIL_MSG( "Invalid font weight value" ); - return wxFontWeight(); + return wxFONTWEIGHT_NORMAL; } bool wxNativeFontInfo::GetUnderlined() const @@ -411,7 +421,7 @@ void wxNativeFontInfo::SetStyle(wxFontStyle style) //case wxFONTSTYLE_NORMAL: } -void wxNativeFontInfo::SetWeight(wxFontWeight weight) +void wxNativeFontInfo::SetNumericWeight(int weight) { m_qtFont.setWeight(ConvertFontWeight(weight)); } diff --git a/src/unix/fontutil.cpp b/src/unix/fontutil.cpp index 22f65947f5..89baf77bef 100644 --- a/src/unix/fontutil.cpp +++ b/src/unix/fontutil.cpp @@ -92,7 +92,12 @@ void wxNativeFontInfo::Free() int wxNativeFontInfo::GetPointSize() const { - return pango_font_description_get_size( description ) / PANGO_SCALE; + return wxRound(GetFractionalPointSize()); +} + +float wxNativeFontInfo::GetFractionalPointSize() const +{ + return ((float) pango_font_description_get_size( description )) / PANGO_SCALE; } wxFontStyle wxNativeFontInfo::GetStyle() const @@ -115,7 +120,7 @@ wxFontStyle wxNativeFontInfo::GetStyle() const return m_style; } -wxFontWeight wxNativeFontInfo::GetWeight() const +int wxNativeFontInfo::GetNumericWeight() const { // We seem to currently initialize only by string. // In that case PANGO_FONT_MASK_WEIGHT is always set. @@ -123,19 +128,7 @@ wxFontWeight wxNativeFontInfo::GetWeight() const // return wxFONTWEIGHT_NORMAL; PangoWeight pango_weight = pango_font_description_get_weight( description ); - - // Until the API can be changed the following ranges of weight values are used: - // wxFONTWEIGHT_LIGHT: 100 .. 349 - range of 250 - // wxFONTWEIGHT_NORMAL: 350 .. 599 - range of 250 - // wxFONTWEIGHT_BOLD: 600 .. 900 - range of 301 (600 is "semibold" already) - - if (pango_weight >= 600) - return wxFONTWEIGHT_BOLD; - - if (pango_weight < 350) - return wxFONTWEIGHT_LIGHT; - - return wxFONTWEIGHT_NORMAL; + return pango_weight; } bool wxNativeFontInfo::GetUnderlined() const @@ -226,7 +219,7 @@ wxFontEncoding wxNativeFontInfo::GetEncoding() const return wxFONTENCODING_SYSTEM; } -void wxNativeFontInfo::SetPointSize(int pointsize) +void wxNativeFontInfo::SetPointSize(float pointsize) { pango_font_description_set_size( description, pointsize * PANGO_SCALE ); } @@ -250,22 +243,9 @@ void wxNativeFontInfo::SetStyle(wxFontStyle style) } } -void wxNativeFontInfo::SetWeight(wxFontWeight weight) +void wxNativeFontInfo::SetNumericWeight(int weight) { - switch (weight) - { - case wxFONTWEIGHT_BOLD: - pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD); - break; - case wxFONTWEIGHT_LIGHT: - pango_font_description_set_weight(description, PANGO_WEIGHT_LIGHT); - break; - default: - wxFAIL_MSG( "unknown font weight" ); - // fall through - case wxFONTWEIGHT_NORMAL: - pango_font_description_set_weight(description, PANGO_WEIGHT_NORMAL); - } + pango_font_description_set_weight(description, (PangoWeight) weight); } void wxNativeFontInfo::SetUnderlined(bool underlined) @@ -726,6 +706,11 @@ void wxNativeFontInfo::SetXFontName(const wxString& xFontName_) } int wxNativeFontInfo::GetPointSize() const +{ + return wxRound(GetFractionalPointSize()); +} + +float wxNativeFontInfo::GetFractionalPointSize() const { const wxString s = GetXFontComponent(wxXLFD_POINTSIZE); @@ -761,13 +746,29 @@ wxFontStyle wxNativeFontInfo::GetStyle() const } } -wxFontWeight wxNativeFontInfo::GetWeight() const +int wxNativeFontInfo::GetNumericWeight() const { - const wxString s = GetXFontComponent(wxXLFD_WEIGHT).MakeLower(); - if ( s.find(wxT("bold")) != wxString::npos || s == wxT("black") ) - return wxFONTWEIGHT_BOLD; - else if ( s == wxT("light") ) + const wxString weight = GetXFontComponent(wxXLFD_WEIGHT).MakeLower(); + if (weight == wxT("thin") || weight == wxT("ultralight")) + return wxFONTWEIGHT_THIN; + else if (weight == wxT("extralight")) + return wxFONTWEIGHT_EXTRALIGHT; + else if (weight == wxT("light")) return wxFONTWEIGHT_LIGHT; + else if (weight == wxT("book") || weight == wxT("semilight") || weight == wxT("demilight")) + return 350; + else if (weight == wxT("medium")) + return wxFONTWEIGHT_MEDIUM; + else if (weight == wxT("semibold") || weight == wxT("demibold")) + return wxFONTWEIGHT_SEMIBOLD; + else if (weight == wxT("bold")) + return wxFONTWEIGHT_BOLD; + else if (weight == wxT("extrabold")) + return wxFONTWEIGHT_EXTRABOLD; + else if (weight == wxT("heavy")) + return wxFONTWEIGHT_HEAVY; + else if (weight == wxT("extraheavy") || weight == wxT("black") || weight == wxT("ultrabold")) + return wxFONTWEIGHT_EXTRAHEAVY; return wxFONTWEIGHT_NORMAL; } @@ -801,7 +802,7 @@ wxFontEncoding wxNativeFontInfo::GetEncoding() const return wxFONTENCODING_MAX; } -void wxNativeFontInfo::SetPointSize(int pointsize) +void wxNativeFontInfo::SetPointSize(float pointsize) { SetXFontComponent(wxXLFD_POINTSIZE, wxString::Format(wxT("%d"), pointsize)); } diff --git a/src/xrc/xmlres.cpp b/src/xrc/xmlres.cpp index 1ac4e51b51..b196ad873c 100644 --- a/src/xrc/xmlres.cpp +++ b/src/xrc/xmlres.cpp @@ -2306,10 +2306,24 @@ wxFont wxXmlResourceHandlerImpl::GetFont(const wxString& param, wxWindow* parent if (hasWeight) { wxString weight = GetParamValue(wxT("weight")); - if (weight == wxT("bold")) - iweight = wxFONTWEIGHT_BOLD; + if (weight == wxT("thin")) + iweight = wxFONTWEIGHT_THIN; + else if (weight == wxT("extralight")) + iweight = wxFONTWEIGHT_EXTRALIGHT; else if (weight == wxT("light")) iweight = wxFONTWEIGHT_LIGHT; + else if (weight == wxT("medium")) + iweight = wxFONTWEIGHT_MEDIUM; + else if (weight == wxT("semibold")) + iweight = wxFONTWEIGHT_SEMIBOLD; + else if (weight == wxT("bold")) + iweight = wxFONTWEIGHT_BOLD; + else if (weight == wxT("extrabold")) + iweight = wxFONTWEIGHT_EXTRABOLD; + else if (weight == wxT("heavy")) + iweight = wxFONTWEIGHT_HEAVY; + else if (weight == wxT("extraheavy")) + iweight = wxFONTWEIGHT_EXTRAHEAVY; else if (weight != wxT("normal")) { ReportParamError