X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/091ef146b7630cd5eca8bcf9f4d97aa122513093..99be3b7c7ccfdd5ad097739482f86e2e096edd77:/src/generic/graphicc.cpp diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index a4d2e774e1..f40b1c5845 100755 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -37,6 +37,7 @@ #endif #include "wx/graphics.h" +#include "wx/rawbmp.h" #if wxUSE_GRAPHICS_CONTEXT @@ -186,6 +187,10 @@ public : 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(); @@ -753,7 +758,9 @@ void wxCairoPathData::AddLineToPoint( wxDouble x , wxDouble y ) void wxCairoPathData::AddPath( const wxGraphicsPathData* path ) { - // TODO + cairo_path_t* p = (cairo_path_t*)path->GetNativePath(); + cairo_append_path(m_pathContext, p); + UnGetNativePath(p); } void wxCairoPathData::CloseSubpath() @@ -866,6 +873,18 @@ void wxCairoMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d, cairo_matrix_init( &m_matrix, a, b, c, d, tx, ty); } +// gets the component valuess of the matrix +void wxCairoMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c, + wxDouble* d, wxDouble* tx, wxDouble* ty) const +{ + if (a) *a = m_matrix.xx; + if (b) *b = m_matrix.yx; + if (c) *c = m_matrix.xy; + if (d) *d = m_matrix.yy; + if (tx) *tx= m_matrix.x0; + if (ty) *ty= m_matrix.y0; +} + // makes this the inverse matrix void wxCairoMatrixData::Invert() { @@ -1012,19 +1031,44 @@ wxCairoContext::~wxCairoContext() } -void wxCairoContext::Clip( const wxRegion & WXUNUSED(region) ) +void wxCairoContext::Clip( const wxRegion& region ) { -// TODO + // Create a path with all the rectangles in the region + wxGraphicsPath path = GetRenderer()->CreatePath(); + wxRegionIterator ri(region); + while (ri) + { + 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); } void wxCairoContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) { -// TODO + // Create a path with this rectangle + wxGraphicsPath path = GetRenderer()->CreatePath(); + path.AddRectangle(x,y,w,h); + + // 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); } void wxCairoContext::ResetClip() { -// TODO + cairo_reset_clip(m_context); } @@ -1102,37 +1146,156 @@ void wxCairoContext::PopState() void wxCairoContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) { - /* - Bitmap* image = Bitmap::FromHBITMAP((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE()); - m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ; - delete image ; - */ + wxCHECK_RET( bmp.IsOk(), wxT("Invalid bitmap in wxCairoContext::DrawBitmap")); + + cairo_surface_t* surface; + int bw = bmp.GetWidth(); + int bh = bmp.GetHeight(); + 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... + if (bmpSource.HasAlpha() || bmpSource.GetMask()) + { + surface = cairo_image_surface_create_for_data( + 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; y<bh; y++) + { + wxAlphaPixelData::Iterator rowStart = p; + for (int x=0; x<bw; x++) + { + // Each pixel in CAIRO_FORMAT_ARGB32 is a 32-bit quantity, + // with alpha in the upper 8 bits, then red, then green, then + // blue. The 32-bit quantities are stored native-endian. + // Pre-multiplied alpha is used. + unsigned char alpha = p.Alpha(); + if (alpha == 0) + *data = 0; + else + *data = ( alpha << 24 + | (p.Red() * alpha/255) << 16 + | (p.Green() * alpha/255) << 8 + | (p.Blue() * alpha/255) ); + ++data; + ++p; + } + p = rowStart; + p.OffsetY(pixData, 1); + } + } + else // no alpha + { + surface = cairo_image_surface_create_for_data( + buffer, CAIRO_FORMAT_RGB24, bw, bh, bw*4); + wxNativePixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh)); + wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data.")); + + wxNativePixelData::Iterator p(pixData); + for (int y=0; y<bh; y++) + { + wxNativePixelData::Iterator rowStart = p; + for (int x=0; x<bw; x++) + { + // Each pixel in CAIRO_FORMAT_RGB24 is a 32-bit quantity, with + // the upper 8 bits unused. Red, Green, and Blue are stored in + // the remaining 24 bits in that order. The 32-bit quantities + // are stored native-endian. + *data = ( p.Red() << 16 | p.Green() << 8 | p.Blue() ); + ++data; + ++p; + } + p = rowStart; + p.OffsetY(pixData, 1); + } + } + + + 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; + 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); + // fill the rectangle using the pattern + cairo_fill(m_context); + + // clean up + cairo_pattern_destroy(pattern); + cairo_surface_destroy(surface); + delete [] buffer; + PopState(); } void wxCairoContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) { - /* - Bitmap* image = Bitmap::FromHICON((HICON)icon.GetHICON()); - m_context->DrawImage(image,(REAL) x,(REAL) y,(REAL) w,(REAL) h) ; - delete image ; - */ + // An icon is a bitmap on wxGTK, so do this the easy way. When we want to + // start using the Cairo backend on other platforms then we may need to + // fiddle with this... + DrawBitmap(icon, x, y, w, h); } void wxCairoContext::DrawText( const wxString &str, wxDouble x, wxDouble y ) { - if ( m_font.IsNull() || str.IsEmpty()) - return ; - cairo_move_to(m_context,x,y); - const wxWX2MBbuf buf(str.mb_str(wxConvUTF8)); + if ( m_font.IsNull() || str.empty()) + return; + ((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); } void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height, wxDouble *descent, wxDouble *externalLeading ) const { - // TODO + if ( m_font.IsNull() || str.empty()) + return; + + ((wxCairoFontData*)m_font.GetRefData())->Apply((wxCairoContext*)this); + + if (width) + { + const wxWX2MBbuf buf(str.mb_str(wxConvUTF8)); + cairo_text_extents_t te; + cairo_text_extents(m_context, buf, &te); + *width = te.width; + } + + if (height || descent || externalLeading) + { + cairo_font_extents_t fe; + cairo_font_extents(m_context, &fe); + + if (height) + *height = fe.height; + if ( descent ) + *descent = fe.descent; + if ( externalLeading ) + *externalLeading = wxMax(0, fe.height - (fe.ascent + fe.descent)); + } } void wxCairoContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const @@ -1166,6 +1329,10 @@ public : virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc); +#ifdef __WXMSW__ + virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc); +#endif + virtual wxGraphicsContext * CreateContextFromNativeContext( void * context ); virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window ); @@ -1224,6 +1391,13 @@ wxGraphicsContext * wxCairoRenderer::CreateContext( const wxWindowDC& dc) return new wxCairoContext(this,dc); } +#ifdef __WXMSW__ +wxGraphicsContext * wxCairoRenderer::CreateContext( const wxMemoryDC& dc) +{ + return NULL; +} +#endif + wxGraphicsContext * wxCairoRenderer::CreateContextFromNativeContext( void * context ) { return new wxCairoContext(this,(cairo_t*)context);