X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c0c133e13b36a923c65f94499554e432bc3a0daa..9c20523110b6601abd001eb6316c563ff1b53af0:/src/generic/graphicc.cpp diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index 7380736638..50965a5b99 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -17,11 +17,11 @@ #if wxUSE_GRAPHICS_CONTEXT +#include "wx/graphics.h" + #ifndef WX_PRECOMP #include "wx/bitmap.h" #include "wx/icon.h" - - #include "wx/dc.h" #include "wx/dcclient.h" #include "wx/dcmemory.h" #include "wx/dcprint.h" @@ -29,37 +29,10 @@ #include "wx/private/graphics.h" #include "wx/rawbmp.h" +#include "wx/vector.h" using namespace std; -//----------------------------------------------------------------------------- -// constants -//----------------------------------------------------------------------------- - -const double RAD2DEG = 180.0 / M_PI; - -//----------------------------------------------------------------------------- -// Local functions -//----------------------------------------------------------------------------- - -static inline double dmin(double a, double b) -{ - return a < b ? a : b; -} -static inline double dmax(double a, double b) -{ - return a > b ? a : b; -} - -static inline double DegToRad(double deg) -{ - return (deg * M_PI) / 180.0; -} -static inline double RadToDeg(double deg) -{ - return (deg * 180.0) / M_PI; -} - //----------------------------------------------------------------------------- // device context implementation // @@ -255,6 +228,8 @@ private : double *m_userLengths; wxPen m_pen; + + wxDECLARE_NO_COPY_CLASS(wxCairoPenData); }; class WXDLLIMPEXP_CORE wxCairoBrushData : public wxGraphicsObjectRefData @@ -311,6 +286,24 @@ private : #endif }; +class wxCairoBitmapData : public wxGraphicsObjectRefData +{ +public: + wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitmap& bmp ); + wxCairoBitmapData( wxGraphicsRenderer* renderer, cairo_surface_t* bitmap ); + ~wxCairoBitmapData(); + + virtual cairo_surface_t* GetCairoSurface() { return m_surface; } + virtual cairo_pattern_t* GetCairoPattern() { return m_pattern; } + virtual wxSize GetSize() { return wxSize(m_width, m_height); } +private : + cairo_surface_t* m_surface; + cairo_pattern_t* m_pattern; + int m_width; + int m_height; + unsigned char* m_buffer; +}; + class WXDLLIMPEXP_CORE wxCairoContext : public wxGraphicsContext { public: @@ -347,7 +340,13 @@ public: virtual void * GetNativeContext(); - virtual bool SetLogicalFunction( wxRasterOperationMode function ); + virtual bool SetAntialiasMode(wxAntialiasMode antialias); + + virtual bool SetCompositionMode(wxCompositionMode op); + + virtual void BeginLayer(wxDouble opacity); + + virtual void EndLayer(); virtual void StrokePath( const wxGraphicsPath& p ); virtual void FillPath( const wxGraphicsPath& p , wxPolygonFillMode fillStyle = wxWINDING_RULE ); @@ -365,6 +364,7 @@ public: // gets the matrix of this context virtual wxGraphicsMatrix GetTransform() const; + virtual void DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ); virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ); virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h ); virtual void PushState(); @@ -374,13 +374,16 @@ public: wxDouble *descent, wxDouble *externalLeading ) const; virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const; +protected: + virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y ); + private: void Init(cairo_t *context); - virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y ); - cairo_t* m_context; + wxVector m_layerOpacities; + wxDECLARE_NO_COPY_CLASS(wxCairoContext); }; @@ -708,7 +711,7 @@ wxCairoFontData::wxCairoFontData( wxGraphicsRenderer* renderer, const wxFont &fo m_underlined = font.GetUnderlined(); #ifdef __WXMAC__ - m_font = cairo_atsui_font_face_create_for_atsu_font_id( font.MacGetATSUFontID() ); + m_font = cairo_quartz_font_face_create_for_cgfont( font.OSXGetCGFont() ); #elif defined(__WXGTK__) m_font = pango_font_description_copy( font.GetNativeFontInfo()->description ); #else @@ -1009,6 +1012,102 @@ void * wxCairoMatrixData::GetNativeMatrix() const return (void*) &m_matrix; } +// wxCairoBitmap implementation +//----------------------------------------------------------------------------- + +wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, cairo_surface_t* bitmap ) : + wxGraphicsObjectRefData( renderer ) +{ + m_surface = bitmap; + m_pattern = cairo_pattern_create_for_surface(m_surface); +} + +wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitmap& bmp ) : wxGraphicsObjectRefData( renderer ) +{ + wxCHECK_RET( bmp.IsOk(), wxT("Invalid bitmap in wxCairoContext::DrawBitmap")); + + int bw = bmp.GetWidth(); + int bh = bmp.GetHeight(); + wxBitmap bmpSource = bmp; // we need a non-const instance + m_buffer = new unsigned char[bw*bh*4]; + wxUint32* data = (wxUint32*)m_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... + if (bmpSource.HasAlpha() || bmpSource.GetMask()) + { + m_surface = cairo_image_surface_create_for_data( + m_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; yCreateBitmap(bmp); + DrawBitmap(bitmap, x, y, w, h); +} +void wxCairoContext::DrawBitmap(const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) +{ PushState(); // In case we're scaling the image by using a width and height different // than the bitmap's size create a pattern transformation on the surface and // draw the transformed pattern. - cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface); - wxDouble scaleX = w / bw; - wxDouble scaleY = h / bh; + wxCairoBitmapData* data = static_cast(bmp.GetRefData()); + cairo_pattern_t* pattern = data->GetCairoPattern(); + wxSize size = data->GetSize(); + + wxDouble scaleX = w / size.GetWidth(); + wxDouble scaleY = h / size.GetHeight(); cairo_scale(m_context, scaleX, scaleY); // prepare to draw the image cairo_translate(m_context, x, y); cairo_set_source(m_context, pattern); // use the original size here since the context is scaled already... - cairo_rectangle(m_context, 0, 0, bw, bh); + cairo_rectangle(m_context, 0, 0, size.GetWidth(), size.GetHeight()); // fill the rectangle using the pattern cairo_fill(m_context); - // clean up - cairo_pattern_destroy(pattern); - cairo_surface_destroy(surface); - delete [] buffer; PopState(); } @@ -1415,8 +1449,8 @@ void wxCairoContext::DoDrawText(const wxString& str, wxDouble x, wxDouble y) 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 (font_data->GetUnderlined()) { PangoAttrList *attrs = pango_attr_list_new(); PangoAttribute *attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); @@ -1536,53 +1570,97 @@ 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 ) +bool wxCairoContext::SetAntialiasMode(wxAntialiasMode antialias) { - if (m_logicalFunction == function) + if (m_antialias == antialias) return true; - cairo_operator_t op; + m_antialias = antialias; - switch ( function ) + cairo_antialias_t antialiasMode; + switch (antialias) { - case wxCOPY: // (default) src - op = CAIRO_OPERATOR_OVER; // (also default) + case wxANTIALIAS_DEFAULT: + antialiasMode = CAIRO_ANTIALIAS_DEFAULT; break; - case wxOR: // src OR dst - op = CAIRO_OPERATOR_ADD; + case wxANTIALIAS_NONE: + antialiasMode = CAIRO_ANTIALIAS_NONE; break; - case wxNO_OP: // dst - op = CAIRO_OPERATOR_DEST; // ignore the source + default: + return false; + } + cairo_set_antialias(m_context, antialiasMode); + return true; +} + +bool wxCairoContext::SetCompositionMode(wxCompositionMode op) +{ + if ( m_composition == op ) + return true; + + m_composition = op; + cairo_operator_t cop; + switch (op) + { + case wxCOMPOSITION_CLEAR: + cop = CAIRO_OPERATOR_CLEAR; break; - case wxCLEAR: // 0 - op = CAIRO_OPERATOR_CLEAR;// clear dst + case wxCOMPOSITION_SOURCE: + cop = CAIRO_OPERATOR_SOURCE; + break; + case wxCOMPOSITION_OVER: + cop = CAIRO_OPERATOR_OVER; + break; + case wxCOMPOSITION_IN: + cop = CAIRO_OPERATOR_IN; + break; + case wxCOMPOSITION_OUT: + cop = CAIRO_OPERATOR_OUT; + break; + case wxCOMPOSITION_ATOP: + cop = CAIRO_OPERATOR_ATOP; + break; + case wxCOMPOSITION_DEST: + cop = CAIRO_OPERATOR_DEST; + break; + case wxCOMPOSITION_DEST_OVER: + cop = CAIRO_OPERATOR_DEST_OVER; + break; + case wxCOMPOSITION_DEST_IN: + cop = CAIRO_OPERATOR_DEST_IN; + break; + case wxCOMPOSITION_DEST_OUT: + cop = CAIRO_OPERATOR_DEST_OUT; + break; + case wxCOMPOSITION_DEST_ATOP: + cop = CAIRO_OPERATOR_DEST_ATOP; + break; + case wxCOMPOSITION_XOR: + cop = CAIRO_OPERATOR_XOR; + break; + case wxCOMPOSITION_ADD: + cop = CAIRO_OPERATOR_ADD; 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); + cairo_set_operator(m_context, cop); return true; } +void wxCairoContext::BeginLayer(wxDouble opacity) +{ + m_layerOpacities.push_back(opacity); + cairo_push_group(m_context); +} + +void wxCairoContext::EndLayer() +{ + float opacity = m_layerOpacities.back(); + m_layerOpacities.pop_back(); + cairo_pop_group_to_source(m_context); + cairo_paint_with_alpha(m_context,opacity); +} //----------------------------------------------------------------------------- // wxCairoRenderer declaration @@ -1636,18 +1714,13 @@ public : 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; - } + virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ); + + // create a graphics bitmap from a native bitmap + virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap ); // 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 + virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h ); private : DECLARE_DYNAMIC_CLASS_NO_COPY(wxCairoRenderer) @@ -1710,6 +1783,9 @@ wxGraphicsContext * wxCairoRenderer::CreateContextFromNativeWindow( void * windo wxGraphicsContext * wxCairoRenderer::CreateMeasuringContext() { +#ifdef __WXGTK__ + return CreateContextFromNativeWindow(gdk_get_default_root_window()); +#endif return NULL; // TODO } @@ -1744,7 +1820,7 @@ wxGraphicsMatrix wxCairoRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble wxGraphicsPen wxCairoRenderer::CreatePen(const wxPen& pen) { - if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT ) + if ( !pen.Ok() || pen.GetStyle() == wxPENSTYLE_TRANSPARENT ) return wxNullGraphicsPen; else { @@ -1756,7 +1832,7 @@ wxGraphicsPen wxCairoRenderer::CreatePen(const wxPen& pen) wxGraphicsBrush wxCairoRenderer::CreateBrush(const wxBrush& brush ) { - if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT ) + if ( !brush.Ok() || brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT ) return wxNullGraphicsBrush; else { @@ -1802,4 +1878,39 @@ wxGraphicsFont wxCairoRenderer::CreateFont( const wxFont &font , const wxColour return wxNullGraphicsFont; } +wxGraphicsBitmap wxCairoRenderer::CreateBitmap( const wxBitmap& bmp ) +{ + if ( bmp.Ok() ) + { + wxGraphicsBitmap p; + p.SetRefData(new wxCairoBitmapData( this , bmp )); + return p; + } + else + return wxNullGraphicsBitmap; +} + +wxGraphicsBitmap wxCairoRenderer::CreateBitmapFromNativeBitmap( void* bitmap ) +{ + if ( bitmap != NULL ) + { + wxGraphicsBitmap p; + p.SetRefData(new wxCairoBitmapData( this , (cairo_surface_t*) bitmap )); + return p; + } + else + return wxNullGraphicsBitmap; +} + +wxGraphicsBitmap +wxCairoRenderer::CreateSubBitmap(const wxGraphicsBitmap& WXUNUSED(bitmap), + wxDouble WXUNUSED(x), + wxDouble WXUNUSED(y), + wxDouble WXUNUSED(w), + wxDouble WXUNUSED(h)) +{ + wxFAIL_MSG("wxCairoRenderer::CreateSubBitmap is not implemented."); + return wxNullGraphicsBitmap; +} + #endif // wxUSE_GRAPHICS_CONTEXT