X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/888dde65f43d5f57e8fb2028b27191cca1741403..ccd5d46c7b69632eaa231e8fc7801dd5af2faaa8:/src/generic/graphicc.cpp diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index af6ee1db26..6b29c3a902 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -12,33 +12,24 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif #if wxUSE_GRAPHICS_CONTEXT -#include "wx/dc.h" - #ifndef WX_PRECOMP -#include "wx/image.h" -#include "wx/window.h" -#include "wx/dc.h" -#include "wx/utils.h" -#include "wx/dialog.h" -#include "wx/app.h" -#include "wx/bitmap.h" -#include "wx/dcmemory.h" -#include "wx/log.h" -#include "wx/icon.h" -#include "wx/dcprint.h" -#include "wx/module.h" + #include "wx/bitmap.h" + #include "wx/icon.h" + + #include "wx/dc.h" + #include "wx/dcclient.h" + #include "wx/dcmemory.h" + #include "wx/dcprint.h" #endif -#include "wx/graphics.h" +#include "wx/private/graphics.h" #include "wx/rawbmp.h" -#include - using namespace std; //----------------------------------------------------------------------------- @@ -107,7 +98,7 @@ static inline double RadToDeg(double deg) #endif #ifdef __WXMAC__ -#include "wx/mac/private.h" +#include "wx/osx/private.h" #include #include #endif @@ -153,7 +144,7 @@ public : /* - // appends a rectangle as a new closed subpath + // appends a rectangle as a new closed subpath virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) ; // appends an ellipsis as a new closed subpath fitting the passed rectangle virtual void AddEllipsis( wxDouble x, wxDouble y, wxDouble w , wxDouble h ) ; @@ -174,7 +165,7 @@ public : // gets the bounding box enclosing all points (possibly including control points) virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const; - virtual bool Contains( wxDouble x, wxDouble y, int fillStyle = wxWINDING_RULE) const; + virtual bool Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle = wxWINDING_RULE) const; private : cairo_t* m_pathContext; @@ -192,13 +183,13 @@ public : virtual void Concat( const wxGraphicsMatrixData *t ); // sets the matrix to the respective values - virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0, + virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0, wxDouble tx=0.0, wxDouble ty=0.0); // gets the component valuess of the matrix virtual void Get(wxDouble* a=NULL, wxDouble* b=NULL, wxDouble* c=NULL, wxDouble* d=NULL, wxDouble* tx=NULL, wxDouble* ty=NULL) const; - + // makes this the inverse matrix virtual void Invert(); @@ -219,7 +210,7 @@ public : virtual void Scale( wxDouble xScale , wxDouble yScale ); // add the rotation to this matrix (radians) - virtual void Rotate( wxDouble angle ); + virtual void Rotate( wxDouble angle ); // // apply the transforms @@ -250,12 +241,12 @@ public: private : double m_width; - + double m_red; double m_green; double m_blue; double m_alpha; - + cairo_line_cap_t m_cap; cairo_line_join_t m_join; @@ -274,7 +265,7 @@ public: ~wxCairoBrushData (); virtual void Apply( wxGraphicsContext* context ); - void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, + void CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, const wxColour&c1, const wxColour&c2 ); void CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, const wxColour &oColor, const wxColour &cColor ); @@ -300,9 +291,11 @@ public: virtual void Apply( wxGraphicsContext* context ); #ifdef __WXGTK__ const PangoFontDescription* GetFont() const { return m_font; } + bool GetUnderlined() const { return m_underlined; } #endif private : double m_size; + bool m_underlined; double m_red; double m_green; double m_blue; @@ -320,11 +313,10 @@ private : class WXDLLIMPEXP_CORE wxCairoContext : public wxGraphicsContext { - DECLARE_NO_COPY_CLASS(wxCairoContext) - public: wxCairoContext( wxGraphicsRenderer* renderer, const wxWindowDC& dc ); wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& dc ); + wxCairoContext( wxGraphicsRenderer* renderer, const wxPrinterDC& dc ); #ifdef __WXGTK__ wxCairoContext( wxGraphicsRenderer* renderer, GdkDrawable *drawable ); #endif @@ -334,7 +326,7 @@ public: virtual ~wxCairoContext(); virtual bool ShouldOffset() const - { + { int penwidth = 0 ; if ( !m_pen.IsNull() ) { @@ -355,8 +347,10 @@ public: virtual void * GetNativeContext(); + virtual bool SetLogicalFunction( wxRasterOperationMode function ); + virtual void StrokePath( const wxGraphicsPath& p ); - virtual void FillPath( const wxGraphicsPath& p , int fillStyle = wxWINDING_RULE ); + virtual void FillPath( const wxGraphicsPath& p , wxPolygonFillMode fillStyle = wxWINDING_RULE ); virtual void Translate( wxDouble dx , wxDouble dy ); virtual void Scale( wxDouble xScale , wxDouble yScale ); @@ -376,15 +370,18 @@ public: virtual void PushState(); virtual void PopState(); - virtual void DrawText( const wxString &str, wxDouble x, wxDouble y); virtual void GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height, wxDouble *descent, wxDouble *externalLeading ) const; virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const; private: void Init(cairo_t *context); - + + virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y ); + cairo_t* m_context; + + DECLARE_NO_COPY_CLASS(wxCairoContext) }; //----------------------------------------------------------------------------- @@ -406,7 +403,7 @@ void wxCairoPenData::Init() wxCairoPenData::wxCairoPenData( wxGraphicsRenderer* renderer, const wxPen &pen ) : wxGraphicsObjectRefData(renderer) -{ +{ Init(); m_pen = pen; m_width = m_pen.GetWidth(); @@ -414,7 +411,7 @@ wxCairoPenData::wxCairoPenData( wxGraphicsRenderer* renderer, const wxPen &pen ) m_width = 0.1; m_red = m_pen.GetColour().Red()/255.0; - m_green = m_pen.GetColour().Green()/255.0; + m_green = m_pen.GetColour().Green()/255.0; m_blue = m_pen.GetColour().Blue()/255.0; m_alpha = m_pen.GetColour().Alpha()/255.0; @@ -476,32 +473,32 @@ wxCairoPenData::wxCairoPenData( wxGraphicsRenderer* renderer, const wxPen &pen ) switch ( m_pen.GetStyle() ) { - case wxSOLID : + case wxPENSTYLE_SOLID : break; - case wxDOT : + case wxPENSTYLE_DOT : m_count = WXSIZEOF(dotted); m_userLengths = new double[ m_count ] ; memcpy( m_userLengths, dotted, sizeof(dotted) ); m_lengths = m_userLengths; break; - case wxLONG_DASH : + case wxPENSTYLE_LONG_DASH : m_lengths = dashed ; m_count = WXSIZEOF(dashed); break; - case wxSHORT_DASH : + case wxPENSTYLE_SHORT_DASH : m_lengths = short_dashed ; m_count = WXSIZEOF(short_dashed); break; - case wxDOT_DASH : + case wxPENSTYLE_DOT_DASH : m_lengths = dotted_dashed ; m_count = WXSIZEOF(dotted_dashed); break; - case wxUSER_DASH : + case wxPENSTYLE_USER_DASH : { wxDash *wxdashes ; m_count = m_pen.GetDashes( &wxdashes ) ; @@ -521,7 +518,7 @@ wxCairoPenData::wxCairoPenData( wxGraphicsRenderer* renderer, const wxPen &pen ) m_lengths = m_userLengths ; } break; - case wxSTIPPLE : + case wxPENSTYLE_STIPPLE : { /* wxBitmap* bmp = pen.GetStipple(); @@ -537,29 +534,30 @@ wxCairoPenData::wxCairoPenData( wxGraphicsRenderer* renderer, const wxPen &pen ) } break; default : - if ( m_pen.GetStyle() >= wxFIRST_HATCH && m_pen.GetStyle() <= wxLAST_HATCH ) + if ( m_pen.GetStyle() >= wxPENSTYLE_FIRST_HATCH + && m_pen.GetStyle() <= wxPENSTYLE_LAST_HATCH ) { /* wxDELETE( m_penBrush ); HatchStyle style = HatchStyleHorizontal; switch( pen.GetStyle() ) { - case wxBDIAGONAL_HATCH : + case wxPENSTYLE_BDIAGONAL_HATCH : style = HatchStyleBackwardDiagonal; break ; - case wxCROSSDIAG_HATCH : + case wxPENSTYLE_CROSSDIAG_HATCH : style = HatchStyleDiagonalCross; break ; - case wxFDIAGONAL_HATCH : + case wxPENSTYLE_FDIAGONAL_HATCH : style = HatchStyleForwardDiagonal; break ; - case wxCROSS_HATCH : + case wxPENSTYLE_CROSS_HATCH : style = HatchStyleCross; break ; - case wxHORIZONTAL_HATCH : + case wxPENSTYLE_HORIZONTAL_HATCH : style = HatchStyleHorizontal; break ; - case wxVERTICAL_HATCH : + case wxPENSTYLE_VERTICAL_HATCH : style = HatchStyleVertical; break ; @@ -597,13 +595,13 @@ wxCairoBrushData::wxCairoBrushData( wxGraphicsRenderer* renderer, const wxBrush : wxGraphicsObjectRefData(renderer) { Init(); - + m_red = brush.GetColour().Red()/255.0; - m_green = brush.GetColour().Green()/255.0; + m_green = brush.GetColour().Green()/255.0; m_blue = brush.GetColour().Blue()/255.0; m_alpha = brush.GetColour().Alpha()/255.0; /* - if ( brush.GetStyle() == wxSOLID) + if ( brush.GetStyle() == wxBRUSHSTYLE_SOLID) { m_brush = new SolidBrush( Color( brush.GetColour().Alpha() , brush.GetColour().Red() , brush.GetColour().Green() , brush.GetColour().Blue() ) ); @@ -613,22 +611,22 @@ wxCairoBrushData::wxCairoBrushData( wxGraphicsRenderer* renderer, const wxBrush HatchStyle style = HatchStyleHorizontal; switch( brush.GetStyle() ) { - case wxBDIAGONAL_HATCH : + case wxBRUSHSTYLE_BDIAGONAL_HATCH : style = HatchStyleBackwardDiagonal; break ; - case wxCROSSDIAG_HATCH : + case wxBRUSHSTYLE_CROSSDIAG_HATCH : style = HatchStyleDiagonalCross; break ; - case wxFDIAGONAL_HATCH : + case wxBRUSHSTYLE_FDIAGONAL_HATCH : style = HatchStyleForwardDiagonal; break ; - case wxCROSS_HATCH : + case wxBRUSHSTYLE_CROSS_HATCH : style = HatchStyleCross; break ; - case wxHORIZONTAL_HATCH : + case wxBRUSHSTYLE_HORIZONTAL_HATCH : style = HatchStyleHorizontal; break ; - case wxVERTICAL_HATCH : + case wxBRUSHSTYLE_VERTICAL_HATCH : style = HatchStyleVertical; break ; @@ -636,7 +634,7 @@ wxCairoBrushData::wxCairoBrushData( wxGraphicsRenderer* renderer, const wxBrush m_brush = new HatchBrush(style,Color( brush.GetColour().Alpha() , brush.GetColour().Red() , brush.GetColour().Green() , brush.GetColour().Blue() ), Color.Transparent ); } - else + else { wxBitmap* bmp = brush.GetStipple(); if ( bmp && bmp->Ok() ) @@ -668,7 +666,7 @@ void wxCairoBrushData::Apply( wxGraphicsContext* context ) } } -void wxCairoBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, +void wxCairoBrushData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, const wxColour&c1, const wxColour&c2 ) { m_brushPattern = cairo_pattern_create_linear(x1,y1,x2,y2); @@ -699,14 +697,15 @@ void wxCairoBrushData::Init() // wxCairoFontData implementation //----------------------------------------------------------------------------- -wxCairoFontData::wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &font, +wxCairoFontData::wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col ) : wxGraphicsObjectRefData(renderer) { m_red = col.Red()/255.0; - m_green = col.Green()/255.0; + m_green = col.Green()/255.0; m_blue = col.Blue()/255.0; m_alpha = col.Alpha()/255.0; m_size = font.GetPointSize(); + m_underlined = font.GetUnderlined(); #ifdef __WXMAC__ m_font = cairo_atsui_font_face_create_for_atsu_font_id( font.MacGetATSUFontID() ); @@ -835,7 +834,7 @@ void wxCairoPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const void wxCairoPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, double startAngle, double endAngle, bool clockwise ) { - // as clockwise means positive in our system (y pointing downwards) + // as clockwise means positive in our system (y pointing downwards) // TODO make this interpretation dependent of the // real device trans if ( clockwise||(endAngle-startAngle)>=2*M_PI) @@ -845,14 +844,14 @@ void wxCairoPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, double startAn } // transforms each point of this path by the matrix -void wxCairoPathData::Transform( const wxGraphicsMatrixData* matrix ) +void wxCairoPathData::Transform( const wxGraphicsMatrixData* matrix ) { // as we don't have a true path object, we have to apply the inverse // matrix to the context cairo_matrix_t m = *((cairo_matrix_t*) matrix->GetNativeMatrix()); cairo_matrix_invert( &m ); cairo_transform(m_pathContext,&m); -} +} // gets the bounding box enclosing all points (possibly including control points) void wxCairoPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const @@ -870,7 +869,7 @@ void wxCairoPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) *x = x1; *w = x2-x1; } - + if( y2 < y1 ) { *y = y2; @@ -883,7 +882,7 @@ void wxCairoPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) } } -bool wxCairoPathData::Contains( wxDouble x, wxDouble y, int WXUNUSED(fillStyle) ) const +bool wxCairoPathData::Contains( wxDouble x, wxDouble y, wxPolygonFillMode WXUNUSED(fillStyle) ) const { return cairo_in_stroke( m_pathContext, x, y) != 0; } @@ -899,25 +898,25 @@ wxCairoMatrixData::wxCairoMatrixData(wxGraphicsRenderer* renderer, const cairo_m m_matrix = *matrix; } -wxCairoMatrixData::~wxCairoMatrixData() +wxCairoMatrixData::~wxCairoMatrixData() { // nothing to do } -wxGraphicsObjectRefData *wxCairoMatrixData::Clone() const +wxGraphicsObjectRefData *wxCairoMatrixData::Clone() const { return new wxCairoMatrixData(GetRenderer(),&m_matrix); } // concatenates the matrix -void wxCairoMatrixData::Concat( const wxGraphicsMatrixData *t ) +void wxCairoMatrixData::Concat( const wxGraphicsMatrixData *t ) { - cairo_matrix_multiply( &m_matrix, &m_matrix, (cairo_matrix_t*) t->GetNativeMatrix()); + cairo_matrix_multiply( &m_matrix, &m_matrix, (cairo_matrix_t*) t->GetNativeMatrix()); } // sets the matrix to the respective values -void wxCairoMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d, - wxDouble tx, wxDouble ty) +void wxCairoMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d, + wxDouble tx, wxDouble ty) { cairo_matrix_init( &m_matrix, a, b, c, d, tx, ty); } @@ -935,21 +934,21 @@ void wxCairoMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c, } // makes this the inverse matrix -void wxCairoMatrixData::Invert() +void wxCairoMatrixData::Invert() { cairo_matrix_invert( &m_matrix ); } // returns true if the elements of the transformation matrix are equal ? -bool wxCairoMatrixData::IsEqual( const wxGraphicsMatrixData* t) const +bool wxCairoMatrixData::IsEqual( const wxGraphicsMatrixData* t) const { const cairo_matrix_t* tm = (cairo_matrix_t*) t->GetNativeMatrix(); - return ( - m_matrix.xx == tm->xx && - m_matrix.yx == tm->yx && - m_matrix.xy == tm->xy && - m_matrix.yy == tm->yy && - m_matrix.x0 == tm->x0 && + return ( + m_matrix.xx == tm->xx && + m_matrix.yx == tm->yx && + m_matrix.xy == tm->xy && + m_matrix.yy == tm->yy && + m_matrix.x0 == tm->x0 && m_matrix.y0 == tm->y0 ) ; } @@ -977,10 +976,10 @@ void wxCairoMatrixData::Scale( wxDouble xScale , wxDouble yScale ) } // add the rotation to this matrix (radians) -void wxCairoMatrixData::Rotate( wxDouble angle ) +void wxCairoMatrixData::Rotate( wxDouble angle ) { cairo_matrix_rotate( &m_matrix, angle) ; -} +} // // apply the transforms @@ -1034,13 +1033,49 @@ public : bool m_offset; } ; +wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxPrinterDC& dc ) +: wxGraphicsContext(renderer) +{ +#ifdef __WXGTK20__ + const wxDCImpl *impl = dc.GetImpl(); + Init( (cairo_t*) impl->GetCairoContext() ); + + wxPoint org = dc.GetDeviceOrigin(); + cairo_translate( m_context, org.x, org.y ); + + double sx,sy; + dc.GetUserScale( &sx, &sy ); + cairo_scale( m_context, sx, sy ); + + org = dc.GetLogicalOrigin(); + cairo_translate( m_context, -org.x, -org.y ); +#endif +} + wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxWindowDC& dc ) : wxGraphicsContext(renderer) { -#ifdef __WXGTK__ +#ifdef __WXGTK20__ wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl(); Init( gdk_cairo_create( impldc->GetGDKWindow() ) ); + +#if 0 + wxGraphicsMatrix matrix = CreateMatrix(); + + wxPoint org = dc.GetDeviceOrigin(); + matrix.Translate( org.x, org.y ); + + org = dc.GetLogicalOrigin(); + matrix.Translate( -org.x, -org.y ); + + double sx,sy; + dc.GetUserScale( &sx, &sy ); + matrix.Scale( sx, sy ); + + ConcatTransform( matrix ); +#endif #endif + #ifdef __WXMAC__ int width, height; dc.GetSize( &width, &height ); @@ -1054,10 +1089,27 @@ wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxWindowDC& wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& dc ) : wxGraphicsContext(renderer) { -#ifdef __WXGTK__ +#ifdef __WXGTK20__ wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl(); Init( gdk_cairo_create( impldc->GetGDKWindow() ) ); + +#if 0 + wxGraphicsMatrix matrix = CreateMatrix(); + + wxPoint org = dc.GetDeviceOrigin(); + matrix.Translate( org.x, org.y ); + + org = dc.GetLogicalOrigin(); + matrix.Translate( -org.x, -org.y ); + + double sx,sy; + dc.GetUserScale( &sx, &sy ); + matrix.Scale( sx, sy ); + + ConcatTransform( matrix ); #endif +#endif + #ifdef __WXMAC__ int width, height; dc.GetSize( &width, &height ); @@ -1068,7 +1120,7 @@ wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& #endif } -#ifdef __WXGTK__ +#ifdef __WXGTK20__ wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, GdkDrawable *drawable ) : wxGraphicsContext(renderer) { @@ -1130,14 +1182,14 @@ void wxCairoContext::Clip( const wxRegion& region ) path.AddRectangle(ri.GetX(), ri.GetY(), ri.GetW(), ri.GetH()); ++ri; } - + // Put it in the context cairo_path_t* cp = (cairo_path_t*) path.GetNativePath() ; cairo_append_path(m_context, cp); // clip to that path cairo_clip(m_context); - path.UnGetNativePath(cp); + path.UnGetNativePath(cp); } void wxCairoContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) @@ -1152,7 +1204,7 @@ void wxCairoContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) // clip to that path cairo_clip(m_context); - path.UnGetNativePath(cp); + path.UnGetNativePath(cp); } void wxCairoContext::ResetClip() @@ -1164,8 +1216,8 @@ void wxCairoContext::ResetClip() void wxCairoContext::StrokePath( const wxGraphicsPath& path ) { if ( !m_pen.IsNull() ) - { - wxCairoOffsetHelper helper( m_context, ShouldOffset() ) ; + { + wxCairoOffsetHelper helper( m_context, ShouldOffset() ) ; cairo_path_t* cp = (cairo_path_t*) path.GetNativePath() ; cairo_append_path(m_context,cp); ((wxCairoPenData*)m_pen.GetRefData())->Apply(this); @@ -1174,7 +1226,7 @@ void wxCairoContext::StrokePath( const wxGraphicsPath& path ) } } -void wxCairoContext::FillPath( const wxGraphicsPath& path , int fillStyle ) +void wxCairoContext::FillPath( const wxGraphicsPath& path , wxPolygonFillMode fillStyle ) { if ( !m_brush.IsNull() ) { @@ -1245,7 +1297,7 @@ void wxCairoContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wx wxBitmap bmpSource = bmp; // we need a non-const instance unsigned char* buffer = new unsigned char[bw*bh*4]; wxUint32* data = (wxUint32*)buffer; - + // Create a surface object and copy the bitmap pixel data to it. if the // image has alpha (or a mask represented as alpha) then we'll use a // different format and iterator than if it doesn't... @@ -1255,7 +1307,7 @@ void wxCairoContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wx buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4); wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh)); wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data.")); - + wxAlphaPixelData::Iterator p(pixData); for (int y=0; yApply(this); +#ifdef __WXGTK__ + size_t datalen = strlen(data); + PangoLayout *layout = pango_cairo_create_layout (m_context); - pango_layout_set_font_description( layout, ((wxCairoFontData*)m_font.GetRefData())->GetFont()); + 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); #else - ((wxCairoFontData*)m_font.GetRefData())->Apply(this); // 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; cairo_font_extents(m_context, &fe); cairo_move_to(m_context, x, y+fe.ascent); - - const wxWX2MBbuf buf(str.mb_str(wxConvUTF8)); - cairo_show_text(m_context,buf); + + cairo_show_text(m_context, data); #endif } void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height, wxDouble *descent, wxDouble *externalLeading ) const { + wxCHECK_RET( !m_font.IsNull(), wxT("wxCairoContext::GetTextExtent - no valid font set") ); + if ( width ) *width = 0; if ( height ) @@ -1386,12 +1454,12 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub if ( externalLeading ) *externalLeading = 0; - if ( m_font.IsNull() || str.empty()) + if ( str.empty()) return; #ifdef __WXGTK__ 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(); @@ -1428,18 +1496,18 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub { cairo_font_extents_t fe; cairo_font_extents(m_context, &fe); - + // some backends have negative descents - + if ( fe.descent < 0 ) fe.descent = -fe.descent; - + if ( fe.height < (fe.ascent + fe.descent ) ) { // some backends are broken re height ... (eg currently ATSUI) fe.height = fe.ascent + fe.descent; } - + if (height) *height = fe.height; if ( descent ) @@ -1455,17 +1523,67 @@ void wxCairoContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths.Empty(); widths.Add(0, text.length()); + wxCHECK_RET( !m_font.IsNull(), wxT("wxCairoContext::GetPartialTextExtents - no valid font set") ); + if (text.empty()) return; // TODO } -void * wxCairoContext::GetNativeContext() +void * wxCairoContext::GetNativeContext() { return m_context; } +// Cairo doesn't support bitwise logical function (a.k.a. ROP, raster output +// mode). Cairo supports Porter-Duff compositing operators, but they are quite +// different, although in some cases have similar names. +bool wxCairoContext::SetLogicalFunction( wxRasterOperationMode function ) +{ + if (m_logicalFunction == function) + return true; + + cairo_operator_t op; + + switch ( function ) + { + case wxCOPY: // (default) src + op = CAIRO_OPERATOR_OVER; // (also default) + break; + case wxOR: // src OR dst + op = CAIRO_OPERATOR_ADD; + break; + case wxNO_OP: // dst + op = CAIRO_OPERATOR_DEST; // ignore the source + break; + case wxCLEAR: // 0 + op = CAIRO_OPERATOR_CLEAR;// clear dst + break; + + case wxAND: // src AND dst + case wxAND_INVERT: // (NOT src) AND dst + case wxAND_REVERSE:// src AND (NOT dst) + case wxEQUIV: // (NOT src) XOR dst + case wxINVERT: // NOT dst + case wxNAND: // (NOT src) OR (NOT dst) + case wxNOR: // (NOT src) AND (NOT dst) + case wxOR_INVERT: // (NOT src) OR dst + case wxOR_REVERSE: // src OR (NOT dst) + case wxSET: // 1 + case wxSRC_INVERT: // NOT src + //wxXOR does _not_ correspond to CAIRO_OPERATOR_XOR + case wxXOR: // src XOR dst + default: + return false; + } + + m_logicalFunction = function; + cairo_set_operator(m_context, op); + return true; +} + + //----------------------------------------------------------------------------- // wxCairoRenderer declaration //----------------------------------------------------------------------------- @@ -1481,6 +1599,7 @@ public : virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc); virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc); + virtual wxGraphicsContext * CreateContext( const wxPrinterDC& dc); virtual wxGraphicsContext * CreateContextFromNativeContext( void * context ); @@ -1496,7 +1615,7 @@ public : // Matrix - virtual wxGraphicsMatrix CreateMatrix( wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0, + virtual wxGraphicsMatrix CreateMatrix( wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0, wxDouble tx=0.0, wxDouble ty=0.0); @@ -1505,10 +1624,10 @@ public : virtual wxGraphicsBrush CreateBrush(const wxBrush& brush ) ; // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 - virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, + virtual wxGraphicsBrush CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, const wxColour&c1, const wxColour&c2) ; - // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) + // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) // with radius r and color cColor virtual wxGraphicsBrush CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, const wxColour &oColor, const wxColour &cColor) ; @@ -1516,6 +1635,20 @@ public : // sets the font virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ; + // create a native bitmap representation +#if 0 + virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) + { + return wxGraphicsBitmap; + } + + // create a subimage from a native image representation + virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) + { + return wxGraphicsBitmap; + } +#endif + private : DECLARE_DYNAMIC_CLASS_NO_COPY(wxCairoRenderer) } ; @@ -1548,6 +1681,18 @@ wxGraphicsContext * wxCairoRenderer::CreateContext( const wxMemoryDC& dc) return new wxCairoContext(this,dc); } +wxGraphicsContext * wxCairoRenderer::CreateContext( const wxPrinterDC& dc) +{ +#ifdef __WXGTK20__ + const wxDCImpl *impl = dc.GetImpl(); + cairo_t* context = (cairo_t*) impl->GetCairoContext(); + if (context) + return new wxCairoContext(this,dc); + else +#endif + return NULL; +} + wxGraphicsContext * wxCairoRenderer::CreateContextFromNativeContext( void * context ) { return new wxCairoContext(this,(cairo_t*)context); @@ -1586,7 +1731,7 @@ wxGraphicsPath wxCairoRenderer::CreatePath() // Matrix -wxGraphicsMatrix wxCairoRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble c, wxDouble d, +wxGraphicsMatrix wxCairoRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble c, wxDouble d, wxDouble tx, wxDouble ty) { @@ -1597,7 +1742,7 @@ wxGraphicsMatrix wxCairoRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble return m; } -wxGraphicsPen wxCairoRenderer::CreatePen(const wxPen& pen) +wxGraphicsPen wxCairoRenderer::CreatePen(const wxPen& pen) { if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT ) return wxNullGraphicsPen; @@ -1609,7 +1754,7 @@ wxGraphicsPen wxCairoRenderer::CreatePen(const wxPen& pen) } } -wxGraphicsBrush wxCairoRenderer::CreateBrush(const wxBrush& brush ) +wxGraphicsBrush wxCairoRenderer::CreateBrush(const wxBrush& brush ) { if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT ) return wxNullGraphicsBrush; @@ -1622,8 +1767,8 @@ wxGraphicsBrush wxCairoRenderer::CreateBrush(const wxBrush& brush ) } // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2 -wxGraphicsBrush wxCairoRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, - const wxColour&c1, const wxColour&c2) +wxGraphicsBrush wxCairoRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2, + const wxColour&c1, const wxColour&c2) { wxGraphicsBrush p; wxCairoBrushData* d = new wxCairoBrushData( this ); @@ -1632,10 +1777,10 @@ wxGraphicsBrush wxCairoRenderer::CreateLinearGradientBrush( wxDouble x1, wxDoubl return p; } -// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) +// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc) // with radius r and color cColor wxGraphicsBrush wxCairoRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius, - const wxColour &oColor, const wxColour &cColor) + const wxColour &oColor, const wxColour &cColor) { wxGraphicsBrush p; wxCairoBrushData* d = new wxCairoBrushData( this ); @@ -1645,10 +1790,10 @@ wxGraphicsBrush wxCairoRenderer::CreateRadialGradientBrush( wxDouble xo, wxDoubl } // sets the font -wxGraphicsFont wxCairoRenderer::CreateFont( const wxFont &font , const wxColour &col ) +wxGraphicsFont wxCairoRenderer::CreateFont( const wxFont &font , const wxColour &col ) { if ( font.Ok() ) - { + { wxGraphicsFont p; p.SetRefData(new wxCairoFontData( this , font, col )); return p;