Further work on bitmap drawing and rescaling.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@24132 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
2003-10-09 00:24:12 +00:00
parent 5d0f365456
commit 5e4e624b51
4 changed files with 372 additions and 240 deletions

View File

@@ -1083,19 +1083,61 @@ wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight,
dst[h*dstbyteperline+width/8] = ~outbyte; dst[h*dstbyteperline+width/8] = ~outbyte;
} }
free( tablex );
free( tabley );
gdk_image_destroy( img ); gdk_image_destroy( img );
if (gc) gdk_gc_unref( gc ); if (gc) gdk_gc_unref( gc );
if (bpp == 1) if (bpp == 1)
{ {
bmp = wxBitmap( (const char *)dst, width, height, 1 ); bmp = wxBitmap( (const char *)dst, width, height, 1 );
wxMask* bmask= new wxMask(bmp);
bmp.SetMask(bmask);
free( dst ); free( dst );
} }
if (GetMask())
{
bpp = 1;
dstbyteperline = width/8*bpp;
if (width*bpp % 8 != 0)
dstbyteperline++;
dst = (char*) malloc(dstbyteperline*height);
img = gdk_image_get( GetMask()->GetBitmap(), 0, 0, GetWidth(), GetHeight() );
for (int h = 0; h < height; h++)
{
char outbyte = 0;
for (int w=0; w<width; w++)
{
guint32 pixval = gdk_image_get_pixel( img, tablex[w], tabley[h] );
if (pixval)
{
char bit=1;
char shift = bit << w % 8;
outbyte |= shift;
}
if ((w+1)%8==0)
{
dst[h*dstbyteperline+w/8]=~outbyte;
outbyte = 0;
}
}
// do not forget the last byte
if (bpp == 1)
dst[h*dstbyteperline+width/8] = ~outbyte;
}
wxBitmap mask_bmp( (const char *)dst, width, height, 1 );
wxMask* mask = new wxMask(mask_bmp);
bmp.SetMask(mask);
free( dst );
gdk_image_destroy( img );
}
free( tablex );
free( tabley );
return bmp; return bmp;
} }

View File

@@ -89,48 +89,42 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable,
gint width, gint width,
gint height) gint height)
{ {
gint src_width, src_height;
#ifndef __WXGTK20__
GdkWindowPrivate *drawable_private;
GdkWindowPrivate *src_private;
GdkGCPrivate *gc_private;
#endif
g_return_if_fail (drawable != NULL); g_return_if_fail (drawable != NULL);
g_return_if_fail (src != NULL); g_return_if_fail (src != NULL);
g_return_if_fail (gc != NULL); g_return_if_fail (gc != NULL);
#ifdef __WXGTK20__ #ifdef __WXGTK20__
// This doesn't seem to exist for bitmaps (1-bit) gint src_width, src_height;
// if (GDK_WINDOW_DESTROYED(drawable) || GDK_WINDOW_DESTROYED(src))
// return;
gdk_drawable_get_size(src, &src_width, &src_height); gdk_drawable_get_size(src, &src_width, &src_height);
#else
drawable_private = (GdkWindowPrivate*) drawable;
src_private = (GdkWindowPrivate*) src;
if (drawable_private->destroyed || src_private->destroyed)
return;
src_width = src_private->width;
src_height = src_private->height;
gc_private = (GdkGCPrivate*) gc;
#endif
if (width == -1) width = src_width; if (width == -1) width = src_width;
if (height == -1) height = src_height; if (height == -1) height = src_height;
#ifdef __WXGTK20__
XCopyPlane( GDK_WINDOW_XDISPLAY(drawable), XCopyPlane( GDK_WINDOW_XDISPLAY(drawable),
GDK_WINDOW_XID(src), GDK_WINDOW_XID(src),
GDK_WINDOW_XID(drawable), GDK_WINDOW_XID(drawable),
GDK_GC_XGC(gc), GDK_GC_XGC(gc),
xsrc, ysrc, xsrc, ysrc,
width, height, width, height,
xdest, ydest, 0, 0,
1 ); 1 );
#else #else
GdkWindowPrivate *drawable_private;
GdkWindowPrivate *src_private;
GdkGCPrivate *gc_private;
drawable_private = (GdkWindowPrivate*) drawable;
src_private = (GdkWindowPrivate*) src;
if (drawable_private->destroyed || src_private->destroyed)
return;
gint src_width = src_private->width;
gint src_height = src_private->height;
gc_private = (GdkGCPrivate*) gc;
if (width == -1) width = src_width;
if (height == -1) height = src_height;
XCopyPlane( drawable_private->xdisplay, XCopyPlane( drawable_private->xdisplay,
src_private->xwindow, src_private->xwindow,
drawable_private->xwindow, drawable_private->xwindow,
@@ -1041,7 +1035,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
bool is_mono = (bitmap.GetBitmap() != NULL); bool is_mono = (bitmap.GetBitmap() != NULL);
/* scale/translate size and position */ // scale/translate size and position
int xx = XLOG2DEV(x); int xx = XLOG2DEV(x);
int yy = YLOG2DEV(y); int yy = YLOG2DEV(y);
@@ -1056,7 +1050,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
int ww = XLOG2DEVREL(w); int ww = XLOG2DEVREL(w);
int hh = YLOG2DEVREL(h); int hh = YLOG2DEVREL(h);
/* compare to current clipping region */ // compare to current clipping region
if (!m_currentClippingRegion.IsNull()) if (!m_currentClippingRegion.IsNull())
{ {
wxRegion tmp( xx,yy,ww,hh ); wxRegion tmp( xx,yy,ww,hh );
@@ -1065,7 +1059,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
return; return;
} }
/* scale bitmap if required */ // scale bitmap if required
wxBitmap use_bitmap; wxBitmap use_bitmap;
if ((w != ww) || (h != hh)) if ((w != ww) || (h != hh))
{ {
@@ -1081,14 +1075,14 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
use_bitmap = bitmap; use_bitmap = bitmap;
} }
/* apply mask if any */ // apply mask if any
GdkBitmap *mask = (GdkBitmap *) NULL; GdkBitmap *mask = (GdkBitmap *) NULL;
if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
GdkBitmap *new_mask = (GdkBitmap*) NULL;
if (useMask && mask) if (useMask && mask)
{ {
GdkBitmap *new_mask = (GdkBitmap*) NULL;
#ifndef __WXGTK20__ // TODO fix crash
if (!m_currentClippingRegion.IsNull()) if (!m_currentClippingRegion.IsNull())
{ {
GdkColor col; GdkColor col;
@@ -1108,7 +1102,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh ); gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
gdk_gc_unref( gc ); gdk_gc_unref( gc );
} }
#endif
if (is_mono) if (is_mono)
{ {
if (new_mask) if (new_mask)
@@ -1125,19 +1119,33 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
gdk_gc_set_clip_mask( m_penGC, mask ); gdk_gc_set_clip_mask( m_penGC, mask );
gdk_gc_set_clip_origin( m_penGC, xx, yy ); gdk_gc_set_clip_origin( m_penGC, xx, yy );
} }
if (new_mask)
gdk_bitmap_unref( new_mask );
} }
/* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
drawing a mono-bitmap (XBitmap) we use the current text GC */ // drawing a mono-bitmap (XBitmap) we use the current text GC
if (is_mono) if (is_mono)
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), 0, 0, xx, yy, -1, -1 ); {
else #ifdef __WXGTK20__
gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); GdkPixmap *bitmap = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, -1 );
GdkGC *gc = gdk_gc_new( bitmap );
gdk_gc_set_foreground( gc, m_textForegroundColour.GetColor() );
gdk_gc_set_background( gc, m_textBackgroundColour.GetColor() );
gdk_wx_draw_bitmap( bitmap, gc, use_bitmap.GetBitmap(), 0, 0, 0, 0, -1, -1 );
/* remove mask again if any */ gdk_draw_drawable( m_window, m_textGC, bitmap, 0, 0, xx, yy, -1, -1 );
gdk_bitmap_unref( bitmap );
gdk_gc_unref( gc );
#else
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), 0, 0, xx, yy, -1, -1 );
#endif
}
else
{
gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
}
// remove mask again if any
if (useMask && mask) if (useMask && mask)
{ {
if (is_mono) if (is_mono)
@@ -1155,6 +1163,9 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
} }
} }
if (new_mask)
gdk_bitmap_unref( new_mask );
} }
bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
@@ -1165,22 +1176,15 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
bool useMask, bool useMask,
wxCoord xsrcMask, wxCoord ysrcMask ) wxCoord xsrcMask, wxCoord ysrcMask )
{ {
/* this is the nth try to get this utterly useless function to
work. it now completely ignores the scaling or translation
of the source dc, but scales correctly on the target dc and
knows about possible mask information in a memory dc. */
wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") ); wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
wxCHECK_MSG( source, FALSE, wxT("invalid source dc") ); wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
if (!m_window) return FALSE; if (!m_window) return FALSE;
#if 1
// transform the source DC coords to the device ones // transform the source DC coords to the device ones
xsrc = source->XLOG2DEV(xsrc); xsrc = source->XLOG2DEV(xsrc);
ysrc = source->YLOG2DEV(ysrc); ysrc = source->YLOG2DEV(ysrc);
#endif
wxClientDC *srcDC = (wxClientDC*)source; wxClientDC *srcDC = (wxClientDC*)source;
wxMemoryDC *memDC = (wxMemoryDC*)source; wxMemoryDC *memDC = (wxMemoryDC*)source;
@@ -1188,10 +1192,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
bool use_bitmap_method = FALSE; bool use_bitmap_method = FALSE;
bool is_mono = FALSE; bool is_mono = FALSE;
/* TODO: use the mask origin when drawing transparently */ // TODO: use the mask origin when drawing transparently
if (xsrcMask == -1 && ysrcMask == -1) if (xsrcMask == -1 && ysrcMask == -1)
{ {
xsrcMask = xsrc; ysrcMask = ysrc; xsrcMask = xsrc;
ysrcMask = ysrc;
} }
if (srcDC->m_isMemDC) if (srcDC->m_isMemDC)
@@ -1200,34 +1205,34 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
is_mono = (memDC->m_selected.GetDepth() == 1); is_mono = (memDC->m_selected.GetDepth() == 1);
/* we use the "XCopyArea" way to copy a memory dc into // we use the "XCopyArea" way to copy a memory dc into
y different window if the memory dc BOTH // a different window if the memory dc BOTH
a) doesn't have any mask or its mask isn't used // a) doesn't have any mask or its mask isn't used
b) it is clipped // b) it is clipped
c) is not 1-bit */ // c) is not 1-bit
if (useMask && (memDC->m_selected.GetMask())) if (useMask && (memDC->m_selected.GetMask()))
{ {
/* we HAVE TO use the direct way for memory dcs // we HAVE TO use the direct way for memory dcs
that have mask since the XCopyArea doesn't know // that have mask since the XCopyArea doesn't know
about masks */ // about masks
use_bitmap_method = TRUE; use_bitmap_method = TRUE;
} }
else if (is_mono) else if (is_mono)
{ {
/* we HAVE TO use the direct way for memory dcs // we HAVE TO use the direct way for memory dcs
that are bitmaps because XCopyArea doesn't cope // that are bitmaps because XCopyArea doesn't cope
with different bit depths */ // with different bit depths
use_bitmap_method = TRUE; use_bitmap_method = TRUE;
} }
else if ((xsrc == 0) && (ysrc == 0) && else if ((xsrc == 0) && (ysrc == 0) &&
(width == memDC->m_selected.GetWidth()) && (width == memDC->m_selected.GetWidth()) &&
(height == memDC->m_selected.GetHeight())) (height == memDC->m_selected.GetHeight()))
{ {
/* we SHOULD use the direct way if all of the bitmap // we SHOULD use the direct way if all of the bitmap
in the memory dc is copied in which case XCopyArea // in the memory dc is copied in which case XCopyArea
wouldn't be able able to boost performace by reducing // wouldn't be able able to boost performace by reducing
the area to be scaled */ // the area to be scaled
use_bitmap_method = TRUE; use_bitmap_method = TRUE;
} }
else else
@@ -1296,10 +1301,10 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
GdkBitmap *mask = (GdkBitmap *) NULL; GdkBitmap *mask = (GdkBitmap *) NULL;
if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
GdkBitmap *new_mask = (GdkBitmap*) NULL;
if (useMask && mask) if (useMask && mask)
{ {
GdkBitmap *new_mask = (GdkBitmap*) NULL;
#ifndef __WXGTK20__ // TODO fix crash
if (!m_currentClippingRegion.IsNull()) if (!m_currentClippingRegion.IsNull())
{ {
GdkColor col; GdkColor col;
@@ -1320,7 +1325,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
gdk_gc_unref( gc ); gdk_gc_unref( gc );
} }
#endif
if (is_mono) if (is_mono)
{ {
if (new_mask) if (new_mask)
@@ -1339,21 +1344,36 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
// was: gdk_gc_set_clip_origin( m_penGC, xx, yy ); // was: gdk_gc_set_clip_origin( m_penGC, xx, yy );
gdk_gc_set_clip_origin( m_penGC, cx, cy ); gdk_gc_set_clip_origin( m_penGC, cx, cy );
} }
if (new_mask)
gdk_bitmap_unref( new_mask );
} }
/* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
drawing a mono-bitmap (XBitmap) we use the current text GC */ // drawing a mono-bitmap (XBitmap) we use the current text GC
if (is_mono) if (is_mono)
{
#ifdef __WXGTK20__
GdkPixmap *bitmap = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, -1 );
GdkGC *gc = gdk_gc_new( bitmap );
gdk_gc_set_foreground( gc, m_textForegroundColour.GetColor() );
gdk_gc_set_background( gc, m_textBackgroundColour.GetColor() );
gdk_wx_draw_bitmap( bitmap, gc, use_bitmap.GetBitmap(), 0, 0, 0, 0, -1, -1 );
gdk_draw_drawable( m_window, m_textGC, bitmap, xsrc, ysrc, cx, cy, cw, ch );
gdk_bitmap_unref( bitmap );
gdk_gc_unref( gc );
#else
// was: gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh ); // was: gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh );
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, cx, cy, cw, ch ); gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, cx, cy, cw, ch );
#endif
}
else else
{
// was: gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh ); // was: gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh );
gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, cx, cy, cw, ch ); gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, cx, cy, cw, ch );
}
/* remove mask again if any */ // remove mask again if any
if (useMask && mask) if (useMask && mask)
{ {
if (is_mono) if (is_mono)
@@ -1371,8 +1391,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
} }
} }
if (new_mask)
gdk_bitmap_unref( new_mask );
} }
else /* use_bitmap_method */ else // use_bitmap_method
{ {
if ((width != ww) || (height != hh)) if ((width != ww) || (height != hh))
{ {
@@ -1391,9 +1414,9 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
} }
else else
{ {
/* No scaling and not a memory dc with a mask either */ // No scaling and not a memory dc with a mask either
/* copy including child window contents */ // copy including child window contents
gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS ); gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
gdk_window_copy_area( m_window, m_penGC, xx, yy, gdk_window_copy_area( m_window, m_penGC, xx, yy,
srcDC->GetWindow(), srcDC->GetWindow(),
@@ -1403,6 +1426,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
} }
SetLogicalFunction( old_logical_func ); SetLogicalFunction( old_logical_func );
return TRUE; return TRUE;
} }

View File

@@ -1083,19 +1083,61 @@ wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight,
dst[h*dstbyteperline+width/8] = ~outbyte; dst[h*dstbyteperline+width/8] = ~outbyte;
} }
free( tablex );
free( tabley );
gdk_image_destroy( img ); gdk_image_destroy( img );
if (gc) gdk_gc_unref( gc ); if (gc) gdk_gc_unref( gc );
if (bpp == 1) if (bpp == 1)
{ {
bmp = wxBitmap( (const char *)dst, width, height, 1 ); bmp = wxBitmap( (const char *)dst, width, height, 1 );
wxMask* bmask= new wxMask(bmp);
bmp.SetMask(bmask);
free( dst ); free( dst );
} }
if (GetMask())
{
bpp = 1;
dstbyteperline = width/8*bpp;
if (width*bpp % 8 != 0)
dstbyteperline++;
dst = (char*) malloc(dstbyteperline*height);
img = gdk_image_get( GetMask()->GetBitmap(), 0, 0, GetWidth(), GetHeight() );
for (int h = 0; h < height; h++)
{
char outbyte = 0;
for (int w=0; w<width; w++)
{
guint32 pixval = gdk_image_get_pixel( img, tablex[w], tabley[h] );
if (pixval)
{
char bit=1;
char shift = bit << w % 8;
outbyte |= shift;
}
if ((w+1)%8==0)
{
dst[h*dstbyteperline+w/8]=~outbyte;
outbyte = 0;
}
}
// do not forget the last byte
if (bpp == 1)
dst[h*dstbyteperline+width/8] = ~outbyte;
}
wxBitmap mask_bmp( (const char *)dst, width, height, 1 );
wxMask* mask = new wxMask(mask_bmp);
bmp.SetMask(mask);
free( dst );
gdk_image_destroy( img );
}
free( tablex );
free( tabley );
return bmp; return bmp;
} }

View File

@@ -89,48 +89,42 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable,
gint width, gint width,
gint height) gint height)
{ {
gint src_width, src_height;
#ifndef __WXGTK20__
GdkWindowPrivate *drawable_private;
GdkWindowPrivate *src_private;
GdkGCPrivate *gc_private;
#endif
g_return_if_fail (drawable != NULL); g_return_if_fail (drawable != NULL);
g_return_if_fail (src != NULL); g_return_if_fail (src != NULL);
g_return_if_fail (gc != NULL); g_return_if_fail (gc != NULL);
#ifdef __WXGTK20__ #ifdef __WXGTK20__
// This doesn't seem to exist for bitmaps (1-bit) gint src_width, src_height;
// if (GDK_WINDOW_DESTROYED(drawable) || GDK_WINDOW_DESTROYED(src))
// return;
gdk_drawable_get_size(src, &src_width, &src_height); gdk_drawable_get_size(src, &src_width, &src_height);
#else
drawable_private = (GdkWindowPrivate*) drawable;
src_private = (GdkWindowPrivate*) src;
if (drawable_private->destroyed || src_private->destroyed)
return;
src_width = src_private->width;
src_height = src_private->height;
gc_private = (GdkGCPrivate*) gc;
#endif
if (width == -1) width = src_width; if (width == -1) width = src_width;
if (height == -1) height = src_height; if (height == -1) height = src_height;
#ifdef __WXGTK20__
XCopyPlane( GDK_WINDOW_XDISPLAY(drawable), XCopyPlane( GDK_WINDOW_XDISPLAY(drawable),
GDK_WINDOW_XID(src), GDK_WINDOW_XID(src),
GDK_WINDOW_XID(drawable), GDK_WINDOW_XID(drawable),
GDK_GC_XGC(gc), GDK_GC_XGC(gc),
xsrc, ysrc, xsrc, ysrc,
width, height, width, height,
xdest, ydest, 0, 0,
1 ); 1 );
#else #else
GdkWindowPrivate *drawable_private;
GdkWindowPrivate *src_private;
GdkGCPrivate *gc_private;
drawable_private = (GdkWindowPrivate*) drawable;
src_private = (GdkWindowPrivate*) src;
if (drawable_private->destroyed || src_private->destroyed)
return;
gint src_width = src_private->width;
gint src_height = src_private->height;
gc_private = (GdkGCPrivate*) gc;
if (width == -1) width = src_width;
if (height == -1) height = src_height;
XCopyPlane( drawable_private->xdisplay, XCopyPlane( drawable_private->xdisplay,
src_private->xwindow, src_private->xwindow,
drawable_private->xwindow, drawable_private->xwindow,
@@ -1041,7 +1035,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
bool is_mono = (bitmap.GetBitmap() != NULL); bool is_mono = (bitmap.GetBitmap() != NULL);
/* scale/translate size and position */ // scale/translate size and position
int xx = XLOG2DEV(x); int xx = XLOG2DEV(x);
int yy = YLOG2DEV(y); int yy = YLOG2DEV(y);
@@ -1056,7 +1050,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
int ww = XLOG2DEVREL(w); int ww = XLOG2DEVREL(w);
int hh = YLOG2DEVREL(h); int hh = YLOG2DEVREL(h);
/* compare to current clipping region */ // compare to current clipping region
if (!m_currentClippingRegion.IsNull()) if (!m_currentClippingRegion.IsNull())
{ {
wxRegion tmp( xx,yy,ww,hh ); wxRegion tmp( xx,yy,ww,hh );
@@ -1065,7 +1059,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
return; return;
} }
/* scale bitmap if required */ // scale bitmap if required
wxBitmap use_bitmap; wxBitmap use_bitmap;
if ((w != ww) || (h != hh)) if ((w != ww) || (h != hh))
{ {
@@ -1081,14 +1075,14 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
use_bitmap = bitmap; use_bitmap = bitmap;
} }
/* apply mask if any */ // apply mask if any
GdkBitmap *mask = (GdkBitmap *) NULL; GdkBitmap *mask = (GdkBitmap *) NULL;
if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
GdkBitmap *new_mask = (GdkBitmap*) NULL;
if (useMask && mask) if (useMask && mask)
{ {
GdkBitmap *new_mask = (GdkBitmap*) NULL;
#ifndef __WXGTK20__ // TODO fix crash
if (!m_currentClippingRegion.IsNull()) if (!m_currentClippingRegion.IsNull())
{ {
GdkColor col; GdkColor col;
@@ -1108,7 +1102,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh ); gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
gdk_gc_unref( gc ); gdk_gc_unref( gc );
} }
#endif
if (is_mono) if (is_mono)
{ {
if (new_mask) if (new_mask)
@@ -1125,19 +1119,33 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
gdk_gc_set_clip_mask( m_penGC, mask ); gdk_gc_set_clip_mask( m_penGC, mask );
gdk_gc_set_clip_origin( m_penGC, xx, yy ); gdk_gc_set_clip_origin( m_penGC, xx, yy );
} }
if (new_mask)
gdk_bitmap_unref( new_mask );
} }
/* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
drawing a mono-bitmap (XBitmap) we use the current text GC */ // drawing a mono-bitmap (XBitmap) we use the current text GC
if (is_mono) if (is_mono)
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), 0, 0, xx, yy, -1, -1 ); {
else #ifdef __WXGTK20__
gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); GdkPixmap *bitmap = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, -1 );
GdkGC *gc = gdk_gc_new( bitmap );
gdk_gc_set_foreground( gc, m_textForegroundColour.GetColor() );
gdk_gc_set_background( gc, m_textBackgroundColour.GetColor() );
gdk_wx_draw_bitmap( bitmap, gc, use_bitmap.GetBitmap(), 0, 0, 0, 0, -1, -1 );
/* remove mask again if any */ gdk_draw_drawable( m_window, m_textGC, bitmap, 0, 0, xx, yy, -1, -1 );
gdk_bitmap_unref( bitmap );
gdk_gc_unref( gc );
#else
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), 0, 0, xx, yy, -1, -1 );
#endif
}
else
{
gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
}
// remove mask again if any
if (useMask && mask) if (useMask && mask)
{ {
if (is_mono) if (is_mono)
@@ -1155,6 +1163,9 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
} }
} }
if (new_mask)
gdk_bitmap_unref( new_mask );
} }
bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
@@ -1165,22 +1176,15 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
bool useMask, bool useMask,
wxCoord xsrcMask, wxCoord ysrcMask ) wxCoord xsrcMask, wxCoord ysrcMask )
{ {
/* this is the nth try to get this utterly useless function to
work. it now completely ignores the scaling or translation
of the source dc, but scales correctly on the target dc and
knows about possible mask information in a memory dc. */
wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") ); wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
wxCHECK_MSG( source, FALSE, wxT("invalid source dc") ); wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
if (!m_window) return FALSE; if (!m_window) return FALSE;
#if 1
// transform the source DC coords to the device ones // transform the source DC coords to the device ones
xsrc = source->XLOG2DEV(xsrc); xsrc = source->XLOG2DEV(xsrc);
ysrc = source->YLOG2DEV(ysrc); ysrc = source->YLOG2DEV(ysrc);
#endif
wxClientDC *srcDC = (wxClientDC*)source; wxClientDC *srcDC = (wxClientDC*)source;
wxMemoryDC *memDC = (wxMemoryDC*)source; wxMemoryDC *memDC = (wxMemoryDC*)source;
@@ -1188,10 +1192,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
bool use_bitmap_method = FALSE; bool use_bitmap_method = FALSE;
bool is_mono = FALSE; bool is_mono = FALSE;
/* TODO: use the mask origin when drawing transparently */ // TODO: use the mask origin when drawing transparently
if (xsrcMask == -1 && ysrcMask == -1) if (xsrcMask == -1 && ysrcMask == -1)
{ {
xsrcMask = xsrc; ysrcMask = ysrc; xsrcMask = xsrc;
ysrcMask = ysrc;
} }
if (srcDC->m_isMemDC) if (srcDC->m_isMemDC)
@@ -1200,34 +1205,34 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
is_mono = (memDC->m_selected.GetDepth() == 1); is_mono = (memDC->m_selected.GetDepth() == 1);
/* we use the "XCopyArea" way to copy a memory dc into // we use the "XCopyArea" way to copy a memory dc into
y different window if the memory dc BOTH // a different window if the memory dc BOTH
a) doesn't have any mask or its mask isn't used // a) doesn't have any mask or its mask isn't used
b) it is clipped // b) it is clipped
c) is not 1-bit */ // c) is not 1-bit
if (useMask && (memDC->m_selected.GetMask())) if (useMask && (memDC->m_selected.GetMask()))
{ {
/* we HAVE TO use the direct way for memory dcs // we HAVE TO use the direct way for memory dcs
that have mask since the XCopyArea doesn't know // that have mask since the XCopyArea doesn't know
about masks */ // about masks
use_bitmap_method = TRUE; use_bitmap_method = TRUE;
} }
else if (is_mono) else if (is_mono)
{ {
/* we HAVE TO use the direct way for memory dcs // we HAVE TO use the direct way for memory dcs
that are bitmaps because XCopyArea doesn't cope // that are bitmaps because XCopyArea doesn't cope
with different bit depths */ // with different bit depths
use_bitmap_method = TRUE; use_bitmap_method = TRUE;
} }
else if ((xsrc == 0) && (ysrc == 0) && else if ((xsrc == 0) && (ysrc == 0) &&
(width == memDC->m_selected.GetWidth()) && (width == memDC->m_selected.GetWidth()) &&
(height == memDC->m_selected.GetHeight())) (height == memDC->m_selected.GetHeight()))
{ {
/* we SHOULD use the direct way if all of the bitmap // we SHOULD use the direct way if all of the bitmap
in the memory dc is copied in which case XCopyArea // in the memory dc is copied in which case XCopyArea
wouldn't be able able to boost performace by reducing // wouldn't be able able to boost performace by reducing
the area to be scaled */ // the area to be scaled
use_bitmap_method = TRUE; use_bitmap_method = TRUE;
} }
else else
@@ -1296,10 +1301,10 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
GdkBitmap *mask = (GdkBitmap *) NULL; GdkBitmap *mask = (GdkBitmap *) NULL;
if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
GdkBitmap *new_mask = (GdkBitmap*) NULL;
if (useMask && mask) if (useMask && mask)
{ {
GdkBitmap *new_mask = (GdkBitmap*) NULL;
#ifndef __WXGTK20__ // TODO fix crash
if (!m_currentClippingRegion.IsNull()) if (!m_currentClippingRegion.IsNull())
{ {
GdkColor col; GdkColor col;
@@ -1320,7 +1325,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
gdk_gc_unref( gc ); gdk_gc_unref( gc );
} }
#endif
if (is_mono) if (is_mono)
{ {
if (new_mask) if (new_mask)
@@ -1339,21 +1344,36 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
// was: gdk_gc_set_clip_origin( m_penGC, xx, yy ); // was: gdk_gc_set_clip_origin( m_penGC, xx, yy );
gdk_gc_set_clip_origin( m_penGC, cx, cy ); gdk_gc_set_clip_origin( m_penGC, cx, cy );
} }
if (new_mask)
gdk_bitmap_unref( new_mask );
} }
/* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
drawing a mono-bitmap (XBitmap) we use the current text GC */ // drawing a mono-bitmap (XBitmap) we use the current text GC
if (is_mono) if (is_mono)
{
#ifdef __WXGTK20__
GdkPixmap *bitmap = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, -1 );
GdkGC *gc = gdk_gc_new( bitmap );
gdk_gc_set_foreground( gc, m_textForegroundColour.GetColor() );
gdk_gc_set_background( gc, m_textBackgroundColour.GetColor() );
gdk_wx_draw_bitmap( bitmap, gc, use_bitmap.GetBitmap(), 0, 0, 0, 0, -1, -1 );
gdk_draw_drawable( m_window, m_textGC, bitmap, xsrc, ysrc, cx, cy, cw, ch );
gdk_bitmap_unref( bitmap );
gdk_gc_unref( gc );
#else
// was: gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh ); // was: gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh );
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, cx, cy, cw, ch ); gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, cx, cy, cw, ch );
#endif
}
else else
{
// was: gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh ); // was: gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh );
gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, cx, cy, cw, ch ); gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, cx, cy, cw, ch );
}
/* remove mask again if any */ // remove mask again if any
if (useMask && mask) if (useMask && mask)
{ {
if (is_mono) if (is_mono)
@@ -1371,8 +1391,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
} }
} }
if (new_mask)
gdk_bitmap_unref( new_mask );
} }
else /* use_bitmap_method */ else // use_bitmap_method
{ {
if ((width != ww) || (height != hh)) if ((width != ww) || (height != hh))
{ {
@@ -1391,9 +1414,9 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
} }
else else
{ {
/* No scaling and not a memory dc with a mask either */ // No scaling and not a memory dc with a mask either
/* copy including child window contents */ // copy including child window contents
gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS ); gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
gdk_window_copy_area( m_window, m_penGC, xx, yy, gdk_window_copy_area( m_window, m_penGC, xx, yy,
srcDC->GetWindow(), srcDC->GetWindow(),
@@ -1403,6 +1426,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
} }
SetLogicalFunction( old_logical_func ); SetLogicalFunction( old_logical_func );
return TRUE; return TRUE;
} }