Allow creating wxGraphicsFont without using wxFont.

This is mostly important to allow using wxImage-based wxGraphicsContext
without requiring X server connection under Unix: as wxFont can't be used
without X server, we needed another way to create wxGraphicsFont in this case.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69360 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2011-10-09 22:07:29 +00:00
parent a95f35b07a
commit fa378d369f
8 changed files with 316 additions and 70 deletions

View File

@ -474,6 +474,7 @@ All (GUI):
- Derive wxAuiNotebook from wxBookCtrlBase (Steven Lamerton).
- Fix tooltips in wxSearchCtrl and other composite controls (Catalin Raceanu).
- Allow converting to and from wxGraphicsBitmap and wxImage directly.
- Allow wxGraphicsFont creation without passing by wxFont.
OSX:

View File

@ -490,8 +490,12 @@ public:
wxDouble xc, wxDouble yc, wxDouble radius,
const wxGraphicsGradientStops& stops) const;
// sets the font
// creates a font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) const;
virtual wxGraphicsFont CreateFont(double sizeInPixels,
const wxString& facename,
int flags = wxFONTFLAG_DEFAULT,
const wxColour& col = *wxBLACK) const;
// create a native bitmap representation
virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) const;
@ -829,6 +833,10 @@ public:
// sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) = 0;
virtual wxGraphicsFont CreateFont(double sizeInPixels,
const wxString& facename,
int flags = wxFONTFLAG_DEFAULT,
const wxColour& col = *wxBLACK) = 0;
// create a native bitmap representation
virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) = 0;

View File

@ -453,6 +453,19 @@ public:
virtual wxGraphicsFont CreateFont(const wxFont& font,
const wxColour& col = *wxBLACK) const;
/**
Creates a font object with the specified attributes.
The use of overload taking wxFont is preferred, see
wxGraphicsRenderer::CreateFont() for more details.
@since 2.9.3
*/
virtual wxGraphicsFont CreateFont(double sizeInPixels,
const wxString& facename,
int flags = wxFONTFLAG_DEFAULT,
const wxColour& col = *wxBLACK) const;
/**
Creates a wxGraphicsContext from a native context. This native context
must be a CGContextRef for Core Graphics, a Graphics pointer for
@ -1027,6 +1040,35 @@ public:
virtual wxGraphicsFont CreateFont(const wxFont& font,
const wxColour& col = *wxBLACK) = 0;
/**
Creates a graphics font with the given characteristics.
If possible, the CreateFont() overload taking wxFont should be used
instead. The main advantage of this overload is that it can be used
without X server connection under Unix when using Cairo.
@param sizeInPixels
Height of the font in user space units, i.e. normally pixels.
Notice that this is different from the overload taking wxFont as
wxFont size is specified in points.
@param facename
The name of the font. The same font name might not be available
under all platforms so the font name can also be empty to use the
default platform font.
@param flags
Combination of wxFontFlag enum elements. Currently only
@c wxFONTFLAG_ITALIC and @c wxFONTFLAG_BOLD are supported. By
default the normal font version is used.
@param col
The font colour, black by default.
@since 2.9.3
*/
virtual wxGraphicsFont CreateFont(double sizeInPixels,
const wxString& facename,
int flags = wxFONTFLAG_DEFAULT,
const wxColour& col = *wxBLACK) = 0;
/**
Creates a native brush with a linear gradient.

View File

@ -866,10 +866,11 @@ private:
wxGraphicsBitmap gb(gc->CreateBitmapFromImage(m_image));
gc->SetFont(*wxNORMAL_FONT, *wxBLACK);
gc->DrawText("Bitmap", 0, HEIGHT/2);
gc->DrawBitmap(m_bitmap, 0, 0, WIDTH, HEIGHT);
wxGraphicsFont gf = gc->CreateFont(wxNORMAL_FONT->GetPixelSize().y, "");
gc->SetFont(gf);
gc->DrawText("Graphics bitmap", 0, (3*HEIGHT)/2);
gc->DrawBitmap(gb, 0, HEIGHT, WIDTH, HEIGHT);
}

View File

@ -837,12 +837,20 @@ wxGraphicsContext::CreateRadialGradientBrush(
);
}
// sets the font
wxGraphicsFont wxGraphicsContext::CreateFont( const wxFont &font , const wxColour &col ) const
{
return GetRenderer()->CreateFont(font,col);
}
wxGraphicsFont
wxGraphicsContext::CreateFont(double size,
const wxString& facename,
int flags,
const wxColour& col) const
{
return GetRenderer()->CreateFont(size, facename, flags, col);
}
wxGraphicsBitmap wxGraphicsContext::CreateBitmap( const wxBitmap& bmp ) const
{
return GetRenderer()->CreateBitmap(bmp);

View File

@ -282,14 +282,24 @@ class wxCairoFontData : public wxGraphicsObjectRefData
{
public:
wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col );
wxCairoFontData(wxGraphicsRenderer* renderer,
double sizeInPixels,
const wxString& facename,
int flags,
const wxColour& col);
~wxCairoFontData();
virtual void Apply( wxGraphicsContext* context );
virtual bool Apply( wxGraphicsContext* context );
#ifdef __WXGTK__
const PangoFontDescription* GetFont() const { return m_font; }
bool GetUnderlined() const { return m_underlined; }
#endif
private :
void InitColour(const wxColour& col);
void InitFontComponents(const wxString& facename,
cairo_font_slant_t slant,
cairo_font_weight_t weight);
double m_size;
bool m_underlined;
double m_red;
@ -300,11 +310,21 @@ private :
cairo_font_face_t *m_font;
#elif defined(__WXGTK__)
PangoFontDescription* m_font;
#else
#endif
// These members are used when the font is created from its face name and
// flags (and not from wxFont) and also even when creating it from wxFont
// on the platforms not covered above.
//
// Notice that we can't use cairo_font_face_t instead of storing those,
// even though it would be simpler and need less #ifdefs, because
// cairo_toy_font_face_create() that we'd need to create it is only
// available in Cairo 1.8 and we require just 1.2 currently. If we do drop
// support for < 1.8 versions in the future it would be definitely better
// to use cairo_toy_font_face_create() instead.
wxCharBuffer m_fontName;
cairo_font_slant_t m_slant;
cairo_font_weight_t m_weight;
#endif
};
class wxCairoBitmapData : public wxGraphicsObjectRefData
@ -806,13 +826,29 @@ void wxCairoBrushData::Init()
// wxCairoFontData implementation
//-----------------------------------------------------------------------------
wxCairoFontData::wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &font,
const wxColour& col ) : wxGraphicsObjectRefData(renderer)
void wxCairoFontData::InitColour(const wxColour& col)
{
m_red = col.Red()/255.0;
m_green = col.Green()/255.0;
m_blue = col.Blue()/255.0;
m_alpha = col.Alpha()/255.0;
}
void
wxCairoFontData::InitFontComponents(const wxString& facename,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
m_fontName = facename.mb_str(wxConvUTF8);
m_slant = slant;
m_weight = weight;
}
wxCairoFontData::wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &font,
const wxColour& col ) : wxGraphicsObjectRefData(renderer)
{
InitColour(col);
m_size = font.GetPointSize();
m_underlined = font.GetUnderlined();
@ -821,35 +857,87 @@ wxCairoFontData::wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &fo
#elif defined(__WXGTK__)
m_font = pango_font_description_copy( font.GetNativeFontInfo()->description );
#else
m_fontName = font.GetFaceName().mb_str(wxConvUTF8);
m_slant = font.GetStyle() == wxFONTSTYLE_ITALIC ? CAIRO_FONT_SLANT_ITALIC:CAIRO_FONT_SLANT_NORMAL;
m_weight = font.GetWeight() == wxFONTWEIGHT_BOLD ? CAIRO_FONT_WEIGHT_BOLD:CAIRO_FONT_WEIGHT_NORMAL;
InitFontComponents
(
font.GetFaceName(),
font.GetStyle() == wxFONTSTYLE_ITALIC ? CAIRO_FONT_SLANT_ITALIC
: CAIRO_FONT_SLANT_NORMAL,
font.GetWeight() == wxFONTWEIGHT_BOLD ? CAIRO_FONT_WEIGHT_BOLD
: CAIRO_FONT_WEIGHT_NORMAL
);
#endif
}
wxCairoFontData::wxCairoFontData(wxGraphicsRenderer* renderer,
double sizeInPixels,
const wxString& facename,
int flags,
const wxColour& col) :
wxGraphicsObjectRefData(renderer)
{
InitColour(col);
// Resolution for Cairo image surfaces is 72 DPI meaning that the sizes in
// points and pixels are identical, so we can just pass the size in pixels
// directly to cairo_set_font_size().
m_size = sizeInPixels;
#if defined(__WXGTK__) || defined(__WXMAC__)
m_font = NULL;
#endif
m_underlined = (flags & wxFONTFLAG_UNDERLINED) != 0;
InitFontComponents
(
facename,
flags & wxFONTFLAG_ITALIC ? CAIRO_FONT_SLANT_ITALIC
: CAIRO_FONT_SLANT_NORMAL,
flags & wxFONTFLAG_BOLD ? CAIRO_FONT_WEIGHT_BOLD
: CAIRO_FONT_WEIGHT_NORMAL
);
}
wxCairoFontData::~wxCairoFontData()
{
#ifdef __WXMAC__
cairo_font_face_destroy( m_font );
if ( m_font )
cairo_font_face_destroy( m_font );
#elif defined(__WXGTK__)
pango_font_description_free( m_font );
if ( m_font )
pango_font_description_free( m_font );
#else
#endif
}
void wxCairoFontData::Apply( wxGraphicsContext* context )
bool wxCairoFontData::Apply( wxGraphicsContext* context )
{
cairo_t * ctext = (cairo_t*) context->GetNativeContext();
cairo_set_source_rgba(ctext,m_red,m_green, m_blue,m_alpha);
#ifdef __WXGTK__
// the rest is done using Pango layouts
if ( m_font )
{
// Nothing to do, the caller uses Pango layout functions to do
// everything.
return true;
}
#elif defined(__WXMAC__)
cairo_set_font_face(ctext, m_font);
cairo_set_font_size(ctext, m_size );
#else
if ( m_font )
{
cairo_set_font_face(ctext, m_font);
cairo_set_font_size(ctext, m_size );
return true;
}
#endif
// If we get here, we must be on a platform without native font support or
// we're using toy Cairo API even under wxGTK/wxMac.
cairo_select_font_face(ctext, m_fontName, m_slant, m_weight );
cairo_set_font_size(ctext, m_size );
#endif
// Indicate that we don't use native fonts for the platforms which care
// about this (currently only wxGTK).
return false;
}
//-----------------------------------------------------------------------------
@ -1900,30 +1988,35 @@ void wxCairoContext::DoDrawText(const wxString& str, wxDouble x, wxDouble y)
if ( !data )
return;
((wxCairoFontData*)m_font.GetRefData())->Apply(this);
#ifdef __WXGTK__
size_t datalen = strlen(data);
PangoLayout *layout = pango_cairo_create_layout (m_context);
wxCairoFontData* font_data = (wxCairoFontData*) m_font.GetRefData();
pango_layout_set_font_description( layout, font_data->GetFont());
pango_layout_set_text(layout, data, datalen);
if (font_data->GetUnderlined())
if ( ((wxCairoFontData*)m_font.GetRefData())->Apply(this) )
{
PangoAttrList *attrs = pango_attr_list_new();
PangoAttribute *attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
pango_attr_list_insert(attrs, attr);
pango_layout_set_attributes(layout, attrs);
pango_attr_list_unref(attrs);
#ifdef __WXGTK__
size_t datalen = strlen(data);
PangoLayout *layout = pango_cairo_create_layout (m_context);
wxCairoFontData* font_data = (wxCairoFontData*) m_font.GetRefData();
pango_layout_set_font_description( layout, font_data->GetFont());
pango_layout_set_text(layout, data, datalen);
if (font_data->GetUnderlined())
{
PangoAttrList *attrs = pango_attr_list_new();
PangoAttribute *attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
pango_attr_list_insert(attrs, attr);
pango_layout_set_attributes(layout, attrs);
pango_attr_list_unref(attrs);
}
cairo_move_to(m_context, x, y);
pango_cairo_show_layout (m_context, layout);
g_object_unref (layout);
// Don't use Cairo text API, we already did everything.
return;
#endif
}
cairo_move_to(m_context, x, y);
pango_cairo_show_layout (m_context, layout);
g_object_unref (layout);
#else
// Cairo's x,y for drawing text is at the baseline, so we need to adjust
// the position we move to by the ascent.
cairo_font_extents_t fe;
@ -1931,7 +2024,6 @@ void wxCairoContext::DoDrawText(const wxString& str, wxDouble x, wxDouble y)
cairo_move_to(m_context, x, y+fe.ascent);
cairo_show_text(m_context, data);
#endif
}
void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
@ -1951,32 +2043,35 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub
if ( str.empty())
return;
if ( ((wxCairoFontData*)m_font.GetRefData())->Apply((wxCairoContext*)this) )
{
#ifdef __WXGTK__
int w, h;
int w, h;
PangoLayout *layout = pango_cairo_create_layout (m_context);
pango_layout_set_font_description( layout, ((wxCairoFontData*)m_font.GetRefData())->GetFont());
const wxCharBuffer data = str.utf8_str();
if ( !data )
{
PangoLayout *layout = pango_cairo_create_layout (m_context);
pango_layout_set_font_description( layout, ((wxCairoFontData*)m_font.GetRefData())->GetFont());
const wxCharBuffer data = str.utf8_str();
if ( !data )
{
return;
}
pango_layout_set_text( layout, data, strlen(data) );
pango_layout_get_pixel_size (layout, &w, &h);
if ( width )
*width = w;
if ( height )
*height = h;
if (descent)
{
PangoLayoutIter *iter = pango_layout_get_iter(layout);
int baseline = pango_layout_iter_get_baseline(iter);
pango_layout_iter_free(iter);
*descent = h - PANGO_PIXELS(baseline);
}
g_object_unref (layout);
return;
#endif
}
pango_layout_set_text( layout, data, strlen(data) );
pango_layout_get_pixel_size (layout, &w, &h);
if ( width )
*width = w;
if ( height )
*height = h;
if (descent)
{
PangoLayoutIter *iter = pango_layout_get_iter(layout);
int baseline = pango_layout_iter_get_baseline(iter);
pango_layout_iter_free(iter);
*descent = h - PANGO_PIXELS(baseline);
}
g_object_unref (layout);
#else
((wxCairoFontData*)m_font.GetRefData())->Apply((wxCairoContext*)this);
if (width)
{
@ -2009,7 +2104,6 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub
if ( externalLeading )
*externalLeading = wxMax(0, fe.height - (fe.ascent + fe.descent));
}
#endif
}
void wxCairoContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
@ -2187,6 +2281,10 @@ public :
// sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
virtual wxGraphicsFont CreateFont(double sizeInPixels,
const wxString& facename,
int flags = wxFONTFLAG_DEFAULT,
const wxColour& col = *wxBLACK);
// create a native bitmap representation
virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap );
@ -2403,7 +2501,6 @@ wxCairoRenderer::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
return p;
}
// sets the font
wxGraphicsFont wxCairoRenderer::CreateFont( const wxFont &font , const wxColour &col )
{
ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont);
@ -2417,6 +2514,19 @@ wxGraphicsFont wxCairoRenderer::CreateFont( const wxFont &font , const wxColour
return wxNullGraphicsFont;
}
wxGraphicsFont
wxCairoRenderer::CreateFont(double sizeInPixels,
const wxString& facename,
int flags,
const wxColour& col)
{
ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont);
wxGraphicsFont font;
font.SetRefData(new wxCairoFontData(this, sizeInPixels, facename, flags, col));
return font;
}
wxGraphicsBitmap wxCairoRenderer::CreateBitmap( const wxBitmap& bmp )
{
ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);

View File

@ -296,6 +296,11 @@ public:
wxGDIPlusFontData( wxGraphicsRenderer* renderer,
const wxFont &font,
const wxColour& col );
wxGDIPlusFontData(wxGraphicsRenderer* renderer,
const wxString& name,
REAL sizeInPixels,
int style,
const wxColour& col);
~wxGDIPlusFontData();
virtual Brush* GetGDIPlusBrush() { return m_textBrush; }
@ -307,7 +312,8 @@ private :
void Init(const wxString& name,
REAL size,
int style,
const wxColour& col);
const wxColour& col,
Unit fontUnit);
Brush* m_textBrush;
Font* m_font;
@ -540,6 +546,11 @@ public :
virtual wxGraphicsFont CreateFont( const wxFont& font,
const wxColour& col);
virtual wxGraphicsFont CreateFont(double size,
const wxString& facename,
int flags = wxFONTFLAG_DEFAULT,
const wxColour& col = *wxBLACK);
// create a graphics bitmap from a native bitmap
virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap );
@ -884,9 +895,10 @@ void
wxGDIPlusFontData::Init(const wxString& name,
REAL size,
int style,
const wxColour& col)
const wxColour& col,
Unit fontUnit)
{
m_font = new Font(name, size, style, UnitPoint);
m_font = new Font(name, size, style, fontUnit);
m_textBrush = new SolidBrush(wxColourToColor(col));
}
@ -904,7 +916,17 @@ wxGDIPlusFontData::wxGDIPlusFontData( wxGraphicsRenderer* renderer,
if ( font.GetWeight() == wxFONTWEIGHT_BOLD )
style |= FontStyleBold;
Init(font.GetFaceName(), font.GetPointSize(), style, col);
Init(font.GetFaceName(), font.GetPointSize(), style, col, UnitPoint);
}
wxGDIPlusFontData::wxGDIPlusFontData(wxGraphicsRenderer* renderer,
const wxString& name,
REAL sizeInPixels,
int style,
const wxColour& col) :
wxGraphicsObjectRefData(renderer)
{
Init(name, sizeInPixels, style, col, UnitPixel);
}
wxGDIPlusFontData::~wxGDIPlusFontData()
@ -2113,6 +2135,31 @@ wxGDIPlusRenderer::CreateFont( const wxFont &font,
return wxNullGraphicsFont;
}
wxGraphicsFont
wxGDIPlusRenderer::CreateFont(double size,
const wxString& facename,
int flags,
const wxColour& col)
{
ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont);
// Convert wxFont flags to GDI+ style:
int style = FontStyleRegular;
if ( flags & wxFONTFLAG_ITALIC )
style |= FontStyleItalic;
if ( flags & wxFONTFLAG_UNDERLINED )
style |= FontStyleUnderline;
if ( flags & wxFONTFLAG_BOLD )
style |= FontStyleBold;
if ( flags & wxFONTFLAG_STRIKETHROUGH )
style |= FontStyleStrikeout;
wxGraphicsFont f;
f.SetRefData(new wxGDIPlusFontData(this, facename, size, style, col));
return f;
}
wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmap( const wxBitmap &bitmap )
{
ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);

View File

@ -2829,6 +2829,10 @@ public :
// sets the font
virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ;
virtual wxGraphicsFont CreateFont(double sizeInPixels,
const wxString& facename,
int flags = wxFONTFLAG_DEFAULT,
const wxColour& col = *wxBLACK);
// create a native bitmap representation
virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) ;
@ -3080,7 +3084,6 @@ wxMacCoreGraphicsRenderer::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
return p;
}
// sets the font
wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const wxColour &col )
{
if ( font.IsOk() )
@ -3093,6 +3096,32 @@ wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const
return wxNullGraphicsFont;
}
wxGraphicsFont
wxMacCoreGraphicsRenderer::CreateFont(double sizeInPixels,
const wxString& facename,
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),
wxFONTFAMILY_DEFAULT,
flags & wxFONTFLAG_ITALIC ? wxFONTSTYLE_ITALIC
: wxFONTSTYLE_NORMAL,
flags & wxFONTFLAG_BOLD ? wxFONTWEIGHT_BOLD
: wxFONTWEIGHT_NORMAL,
(flags & wxFONTFLAG_UNDERLINED) != 0,
facename);
wxGraphicsFont f;
f.SetRefData(new wxMacCoreGraphicsFontData(this, font, col));
return f;
}
//
// CoreGraphics Helper Methods
//