Applied new DoDrawBitmap() and DoBlit() from 2_4

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24145 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling 2003-10-09 20:03:17 +00:00
parent 783da8450c
commit d90c9596c1
2 changed files with 360 additions and 348 deletions

View File

@ -92,48 +92,42 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable,
gint width,
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 (src != NULL);
g_return_if_fail (gc != NULL);
#ifdef __WXGTK20__
// This doesn't seem to exist for bitmaps (1-bit)
// if (GDK_WINDOW_DESTROYED(drawable) || GDK_WINDOW_DESTROYED(src))
// return;
gint 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 (height == -1) height = src_height;
#ifdef __WXGTK20__
XCopyPlane( GDK_WINDOW_XDISPLAY(drawable),
GDK_WINDOW_XID(src),
GDK_WINDOW_XID(drawable),
GDK_GC_XGC(gc),
xsrc, ysrc,
width, height,
xdest, ydest,
0, 0,
1 );
#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,
src_private->xwindow,
drawable_private->xwindow,
@ -1053,7 +1047,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
bool is_mono = (bitmap.GetBitmap() != NULL);
/* scale/translate size and position */
// scale/translate size and position
int xx = XLOG2DEV(x);
int yy = YLOG2DEV(y);
@ -1068,7 +1062,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
int ww = XLOG2DEVREL(w);
int hh = YLOG2DEVREL(h);
/* compare to current clipping region */
// compare to current clipping region
if (!m_currentClippingRegion.IsNull())
{
wxRegion tmp( xx,yy,ww,hh );
@ -1077,79 +1071,82 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
return;
}
/* scale bitmap if required */
wxBitmap use_bitmap;
// scale bitmap if required
wxBitmap use_bitmap = bitmap;
if ((w != ww) || (h != hh))
{
wxImage image = bitmap.ConvertToImage();
image.Rescale( ww, hh );
if (is_mono)
use_bitmap = wxBitmap(image.ConvertToMono(255,255,255), 1);
else
use_bitmap = wxBitmap(image);
}
else
{
use_bitmap = bitmap;
}
use_bitmap = use_bitmap.Rescale( 0, 0, ww, hh, ww, hh );
/* apply mask if any */
// apply mask if any
GdkBitmap *mask = (GdkBitmap *) NULL;
if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
if (useMask && mask)
GdkBitmap *new_mask = (GdkBitmap*) NULL;
if (useMask && mask)
{
if (!m_currentClippingRegion.IsNull())
{
GdkBitmap *new_mask = (GdkBitmap*) NULL;
#ifndef __WXGTK20__ // TODO fix crash
if (!m_currentClippingRegion.IsNull())
{
GdkColor col;
new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
GdkGC *gc = gdk_gc_new( new_mask );
col.pixel = 0;
gdk_gc_set_foreground( gc, &col );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
col.pixel = 0;
gdk_gc_set_background( gc, &col );
col.pixel = 1;
gdk_gc_set_foreground( gc, &col );
gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
gdk_gc_set_clip_origin( gc, -xx, -yy );
gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
gdk_gc_set_stipple( gc, mask );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
gdk_gc_unref( gc );
}
#endif
if (is_mono)
{
if (new_mask)
gdk_gc_set_clip_mask( m_textGC, new_mask );
else
gdk_gc_set_clip_mask( m_textGC, mask );
gdk_gc_set_clip_origin( m_textGC, xx, yy );
}
else
{
if (new_mask)
gdk_gc_set_clip_mask( m_penGC, new_mask );
else
gdk_gc_set_clip_mask( m_penGC, mask );
gdk_gc_set_clip_origin( m_penGC, xx, yy );
}
if (new_mask)
gdk_bitmap_unref( new_mask );
GdkColor col;
new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
GdkGC *gc = gdk_gc_new( new_mask );
col.pixel = 0;
gdk_gc_set_foreground( gc, &col );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
col.pixel = 0;
gdk_gc_set_background( gc, &col );
col.pixel = 1;
gdk_gc_set_foreground( gc, &col );
gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
gdk_gc_set_clip_origin( gc, -xx, -yy );
gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
gdk_gc_set_stipple( gc, mask );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
gdk_gc_unref( gc );
}
if (is_mono)
{
if (new_mask)
gdk_gc_set_clip_mask( m_textGC, new_mask );
else
gdk_gc_set_clip_mask( m_textGC, mask );
gdk_gc_set_clip_origin( m_textGC, xx, yy );
}
else
{
if (new_mask)
gdk_gc_set_clip_mask( m_penGC, new_mask );
else
gdk_gc_set_clip_mask( m_penGC, mask );
gdk_gc_set_clip_origin( m_penGC, xx, yy );
}
}
/* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
drawing a mono-bitmap (XBitmap) we use the current text GC */
// Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
// drawing a mono-bitmap (XBitmap) we use the current text GC
if (is_mono)
{
#ifdef __WXGTK20__
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 );
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 */
// remove mask again if any
if (useMask && mask)
{
if (is_mono)
@ -1167,6 +1164,9 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
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,
@ -1177,22 +1177,15 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
bool useMask,
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( source, FALSE, wxT("invalid source dc") );
if (!m_window) return FALSE;
#if 1
// transform the source DC coords to the device ones
xsrc = source->XLOG2DEV(xsrc);
ysrc = source->YLOG2DEV(ysrc);
#endif
wxClientDC *srcDC = (wxClientDC*)source;
wxMemoryDC *memDC = (wxMemoryDC*)source;
@ -1200,45 +1193,47 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
bool use_bitmap_method = 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)
{
xsrcMask = xsrc; ysrcMask = ysrc;
xsrcMask = xsrc;
ysrcMask = ysrc;
}
if (srcDC->m_isMemDC)
{
if (!memDC->m_selected.Ok()) return FALSE;
/* we use the "XCopyArea" way to copy a memory dc into
y different window if the memory dc BOTH
a) doesn't have any mask or its mask isn't used
b) it is clipped
c) is not 1-bit */
is_mono = (memDC->m_selected.GetDepth() == 1);
// we use the "XCopyArea" way to copy a memory dc into
// a different window if the memory dc BOTH
// a) doesn't have any mask or its mask isn't used
// b) it is clipped
// c) is not 1-bit
if (useMask && (memDC->m_selected.GetMask()))
{
/* we HAVE TO use the direct way for memory dcs
that have mask since the XCopyArea doesn't know
about masks */
// we HAVE TO use the direct way for memory dcs
// that have mask since the XCopyArea doesn't know
// about masks
use_bitmap_method = TRUE;
}
else if (memDC->m_selected.GetDepth() == 1)
else if (is_mono)
{
/* we HAVE TO use the direct way for memory dcs
that are bitmaps because XCopyArea doesn't cope
with different bit depths */
is_mono = TRUE;
// we HAVE TO use the direct way for memory dcs
// that are bitmaps because XCopyArea doesn't cope
// with different bit depths
use_bitmap_method = TRUE;
}
else if ((xsrc == 0) && (ysrc == 0) &&
(width == memDC->m_selected.GetWidth()) &&
(height == memDC->m_selected.GetHeight()))
{
/* we SHOULD use the direct way if all of the bitmap
in the memory dc is copied in which case XCopyArea
wouldn't be able able to boost performace by reducing
the area to be scaled */
// we SHOULD use the direct way if all of the bitmap
// in the memory dc is copied in which case XCopyArea
// wouldn't be able able to boost performace by reducing
// the area to be scaled
use_bitmap_method = TRUE;
}
else
@ -1250,14 +1245,14 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
CalcBoundingBox( xdest, ydest );
CalcBoundingBox( xdest + width, ydest + height );
/* scale/translate size and position */
// scale/translate size and position
wxCoord xx = XLOG2DEV(xdest);
wxCoord yy = YLOG2DEV(ydest);
wxCoord ww = XLOG2DEVREL(width);
wxCoord hh = YLOG2DEVREL(height);
/* compare to current clipping region */
// compare to current clipping region
if (!m_currentClippingRegion.IsNull())
{
wxRegion tmp( xx,yy,ww,hh );
@ -1271,39 +1266,46 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
if (use_bitmap_method)
{
/* scale/translate bitmap size */
// scale/translate bitmap size
wxCoord bm_width = memDC->m_selected.GetWidth();
wxCoord bm_height = memDC->m_selected.GetHeight();
// get clip coords
wxRegion tmp( xx,yy,ww,hh );
tmp.Intersect( m_currentClippingRegion );
wxCoord cx,cy,cw,ch;
tmp.GetBox(cx,cy,cw,ch);
// interpret userscale of src too
double xsc,ysc;
memDC->GetUserScale(&xsc,&ysc);
bm_width = (int) (bm_width / xsc);
bm_height = (int) (bm_height / ysc);
wxCoord bm_ww = XLOG2DEVREL( bm_width );
wxCoord bm_hh = YLOG2DEVREL( bm_height );
/* scale bitmap if required */
// scale bitmap if required
wxBitmap use_bitmap;
if ((bm_width != bm_ww) || (bm_height != bm_hh))
{
wxImage image = memDC->m_selected.ConvertToImage();
image = image.Scale( bm_ww, bm_hh );
if (is_mono)
use_bitmap = wxBitmap(image.ConvertToMono(255,255,255), 1);
else
use_bitmap = wxBitmap(image);
use_bitmap = memDC->m_selected.Rescale(cx-xx,cy-yy,cw,ch,bm_ww,bm_hh);
}
else
{
// FIXME: use cx,cy,cw,ch here, too?
use_bitmap = memDC->m_selected;
}
/* apply mask if any */
// apply mask if any
GdkBitmap *mask = (GdkBitmap *) NULL;
if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
GdkBitmap *new_mask = (GdkBitmap*) NULL;
if (useMask && mask)
{
GdkBitmap *new_mask = (GdkBitmap*) NULL;
#ifndef __WXGTK20__ // TODO fix crash
if (!m_currentClippingRegion.IsNull())
{
GdkColor col;
@ -1317,20 +1319,22 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
col.pixel = 1;
gdk_gc_set_foreground( gc, &col );
gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
gdk_gc_set_clip_origin( gc, -xx, -yy );
// was: gdk_gc_set_clip_origin( gc, -xx, -yy );
gdk_gc_set_clip_origin( gc, -cx, -cy );
gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
gdk_gc_set_stipple( gc, mask );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
gdk_gc_unref( gc );
}
#endif
if (is_mono)
{
if (new_mask)
gdk_gc_set_clip_mask( m_textGC, new_mask );
else
gdk_gc_set_clip_mask( m_textGC, mask );
gdk_gc_set_clip_origin( m_textGC, xx, yy );
// was: gdk_gc_set_clip_origin( m_textGC, xx, yy );
gdk_gc_set_clip_origin( m_textGC, cx, cy );
}
else
{
@ -1338,21 +1342,39 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
gdk_gc_set_clip_mask( m_penGC, new_mask );
else
gdk_gc_set_clip_mask( m_penGC, mask );
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 );
}
if (new_mask)
gdk_bitmap_unref( new_mask );
}
/* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
drawing a mono-bitmap (XBitmap) we use the current text GC */
// Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
// drawing a mono-bitmap (XBitmap) we use the current text GC
if (is_mono)
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh );
{
#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 );
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, cx, cy, cw, ch );
#endif
}
else
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 );
}
/* remove mask again if any */
// remove mask again if any
if (useMask && mask)
{
if (is_mono)
@ -1370,49 +1392,32 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
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))
{
/* draw source window into a bitmap as we cannot scale
a window in contrast to a bitmap. this would actually
work with memory dcs as well, but we'd lose the mask
information and waste one step in this process since
a memory already has a bitmap. all this is slightly
inefficient as we could take an XImage directly from
an X window, but we'd then also have to care that
the window is not outside the screen (in which case
we'd get a BadMatch or what not).
Is a double XGetImage and combined XGetPixel and
XPutPixel really faster? I'm not sure. look at wxXt
for a different implementation of the same problem. */
wxBitmap bitmap( width, height );
/* copy including child window contents */
gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0,
srcDC->GetWindow(),
xsrc, ysrc, width, height );
gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
/* scale image */
wxImage image = bitmap.ConvertToImage();
image = image.Scale( ww, hh );
/* convert to bitmap */
bitmap = wxBitmap(image);
/* draw scaled bitmap */
gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
// get clip coords
wxRegion tmp( xx,yy,ww,hh );
tmp.Intersect( m_currentClippingRegion );
wxCoord cx,cy,cw,ch;
tmp.GetBox(cx,cy,cw,ch);
// rescale bitmap
wxBitmap bitmap = memDC->m_selected.Rescale( cx-xx, cy-yy, cw, ch, ww, hh );
// draw scaled bitmap
// was: gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, cx, cy, -1, -1 );
}
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_window_copy_area( m_window, m_penGC, xx, yy,
srcDC->GetWindow(),
@ -1422,6 +1427,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
}
SetLogicalFunction( old_logical_func );
return TRUE;
}
@ -1457,7 +1463,7 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
int w,h;
if (m_scaleY != 1.0)
if (abs(m_scaleY - 1.0) < 0.00001)
{
// If there is a user or actually any scale applied to
// the device context, scale the font.

View File

@ -92,48 +92,42 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable,
gint width,
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 (src != NULL);
g_return_if_fail (gc != NULL);
#ifdef __WXGTK20__
// This doesn't seem to exist for bitmaps (1-bit)
// if (GDK_WINDOW_DESTROYED(drawable) || GDK_WINDOW_DESTROYED(src))
// return;
gint 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 (height == -1) height = src_height;
#ifdef __WXGTK20__
XCopyPlane( GDK_WINDOW_XDISPLAY(drawable),
GDK_WINDOW_XID(src),
GDK_WINDOW_XID(drawable),
GDK_GC_XGC(gc),
xsrc, ysrc,
width, height,
xdest, ydest,
0, 0,
1 );
#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,
src_private->xwindow,
drawable_private->xwindow,
@ -1053,7 +1047,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
bool is_mono = (bitmap.GetBitmap() != NULL);
/* scale/translate size and position */
// scale/translate size and position
int xx = XLOG2DEV(x);
int yy = YLOG2DEV(y);
@ -1068,7 +1062,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
int ww = XLOG2DEVREL(w);
int hh = YLOG2DEVREL(h);
/* compare to current clipping region */
// compare to current clipping region
if (!m_currentClippingRegion.IsNull())
{
wxRegion tmp( xx,yy,ww,hh );
@ -1077,79 +1071,82 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
return;
}
/* scale bitmap if required */
wxBitmap use_bitmap;
// scale bitmap if required
wxBitmap use_bitmap = bitmap;
if ((w != ww) || (h != hh))
{
wxImage image = bitmap.ConvertToImage();
image.Rescale( ww, hh );
if (is_mono)
use_bitmap = wxBitmap(image.ConvertToMono(255,255,255), 1);
else
use_bitmap = wxBitmap(image);
}
else
{
use_bitmap = bitmap;
}
use_bitmap = use_bitmap.Rescale( 0, 0, ww, hh, ww, hh );
/* apply mask if any */
// apply mask if any
GdkBitmap *mask = (GdkBitmap *) NULL;
if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
if (useMask && mask)
GdkBitmap *new_mask = (GdkBitmap*) NULL;
if (useMask && mask)
{
if (!m_currentClippingRegion.IsNull())
{
GdkBitmap *new_mask = (GdkBitmap*) NULL;
#ifndef __WXGTK20__ // TODO fix crash
if (!m_currentClippingRegion.IsNull())
{
GdkColor col;
new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
GdkGC *gc = gdk_gc_new( new_mask );
col.pixel = 0;
gdk_gc_set_foreground( gc, &col );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
col.pixel = 0;
gdk_gc_set_background( gc, &col );
col.pixel = 1;
gdk_gc_set_foreground( gc, &col );
gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
gdk_gc_set_clip_origin( gc, -xx, -yy );
gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
gdk_gc_set_stipple( gc, mask );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
gdk_gc_unref( gc );
}
#endif
if (is_mono)
{
if (new_mask)
gdk_gc_set_clip_mask( m_textGC, new_mask );
else
gdk_gc_set_clip_mask( m_textGC, mask );
gdk_gc_set_clip_origin( m_textGC, xx, yy );
}
else
{
if (new_mask)
gdk_gc_set_clip_mask( m_penGC, new_mask );
else
gdk_gc_set_clip_mask( m_penGC, mask );
gdk_gc_set_clip_origin( m_penGC, xx, yy );
}
if (new_mask)
gdk_bitmap_unref( new_mask );
GdkColor col;
new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
GdkGC *gc = gdk_gc_new( new_mask );
col.pixel = 0;
gdk_gc_set_foreground( gc, &col );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
col.pixel = 0;
gdk_gc_set_background( gc, &col );
col.pixel = 1;
gdk_gc_set_foreground( gc, &col );
gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
gdk_gc_set_clip_origin( gc, -xx, -yy );
gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
gdk_gc_set_stipple( gc, mask );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
gdk_gc_unref( gc );
}
if (is_mono)
{
if (new_mask)
gdk_gc_set_clip_mask( m_textGC, new_mask );
else
gdk_gc_set_clip_mask( m_textGC, mask );
gdk_gc_set_clip_origin( m_textGC, xx, yy );
}
else
{
if (new_mask)
gdk_gc_set_clip_mask( m_penGC, new_mask );
else
gdk_gc_set_clip_mask( m_penGC, mask );
gdk_gc_set_clip_origin( m_penGC, xx, yy );
}
}
/* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
drawing a mono-bitmap (XBitmap) we use the current text GC */
// Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
// drawing a mono-bitmap (XBitmap) we use the current text GC
if (is_mono)
{
#ifdef __WXGTK20__
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 );
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 */
// remove mask again if any
if (useMask && mask)
{
if (is_mono)
@ -1167,6 +1164,9 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
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,
@ -1177,22 +1177,15 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
bool useMask,
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( source, FALSE, wxT("invalid source dc") );
if (!m_window) return FALSE;
#if 1
// transform the source DC coords to the device ones
xsrc = source->XLOG2DEV(xsrc);
ysrc = source->YLOG2DEV(ysrc);
#endif
wxClientDC *srcDC = (wxClientDC*)source;
wxMemoryDC *memDC = (wxMemoryDC*)source;
@ -1200,45 +1193,47 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
bool use_bitmap_method = 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)
{
xsrcMask = xsrc; ysrcMask = ysrc;
xsrcMask = xsrc;
ysrcMask = ysrc;
}
if (srcDC->m_isMemDC)
{
if (!memDC->m_selected.Ok()) return FALSE;
/* we use the "XCopyArea" way to copy a memory dc into
y different window if the memory dc BOTH
a) doesn't have any mask or its mask isn't used
b) it is clipped
c) is not 1-bit */
is_mono = (memDC->m_selected.GetDepth() == 1);
// we use the "XCopyArea" way to copy a memory dc into
// a different window if the memory dc BOTH
// a) doesn't have any mask or its mask isn't used
// b) it is clipped
// c) is not 1-bit
if (useMask && (memDC->m_selected.GetMask()))
{
/* we HAVE TO use the direct way for memory dcs
that have mask since the XCopyArea doesn't know
about masks */
// we HAVE TO use the direct way for memory dcs
// that have mask since the XCopyArea doesn't know
// about masks
use_bitmap_method = TRUE;
}
else if (memDC->m_selected.GetDepth() == 1)
else if (is_mono)
{
/* we HAVE TO use the direct way for memory dcs
that are bitmaps because XCopyArea doesn't cope
with different bit depths */
is_mono = TRUE;
// we HAVE TO use the direct way for memory dcs
// that are bitmaps because XCopyArea doesn't cope
// with different bit depths
use_bitmap_method = TRUE;
}
else if ((xsrc == 0) && (ysrc == 0) &&
(width == memDC->m_selected.GetWidth()) &&
(height == memDC->m_selected.GetHeight()))
{
/* we SHOULD use the direct way if all of the bitmap
in the memory dc is copied in which case XCopyArea
wouldn't be able able to boost performace by reducing
the area to be scaled */
// we SHOULD use the direct way if all of the bitmap
// in the memory dc is copied in which case XCopyArea
// wouldn't be able able to boost performace by reducing
// the area to be scaled
use_bitmap_method = TRUE;
}
else
@ -1250,14 +1245,14 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
CalcBoundingBox( xdest, ydest );
CalcBoundingBox( xdest + width, ydest + height );
/* scale/translate size and position */
// scale/translate size and position
wxCoord xx = XLOG2DEV(xdest);
wxCoord yy = YLOG2DEV(ydest);
wxCoord ww = XLOG2DEVREL(width);
wxCoord hh = YLOG2DEVREL(height);
/* compare to current clipping region */
// compare to current clipping region
if (!m_currentClippingRegion.IsNull())
{
wxRegion tmp( xx,yy,ww,hh );
@ -1271,39 +1266,46 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
if (use_bitmap_method)
{
/* scale/translate bitmap size */
// scale/translate bitmap size
wxCoord bm_width = memDC->m_selected.GetWidth();
wxCoord bm_height = memDC->m_selected.GetHeight();
// get clip coords
wxRegion tmp( xx,yy,ww,hh );
tmp.Intersect( m_currentClippingRegion );
wxCoord cx,cy,cw,ch;
tmp.GetBox(cx,cy,cw,ch);
// interpret userscale of src too
double xsc,ysc;
memDC->GetUserScale(&xsc,&ysc);
bm_width = (int) (bm_width / xsc);
bm_height = (int) (bm_height / ysc);
wxCoord bm_ww = XLOG2DEVREL( bm_width );
wxCoord bm_hh = YLOG2DEVREL( bm_height );
/* scale bitmap if required */
// scale bitmap if required
wxBitmap use_bitmap;
if ((bm_width != bm_ww) || (bm_height != bm_hh))
{
wxImage image = memDC->m_selected.ConvertToImage();
image = image.Scale( bm_ww, bm_hh );
if (is_mono)
use_bitmap = wxBitmap(image.ConvertToMono(255,255,255), 1);
else
use_bitmap = wxBitmap(image);
use_bitmap = memDC->m_selected.Rescale(cx-xx,cy-yy,cw,ch,bm_ww,bm_hh);
}
else
{
// FIXME: use cx,cy,cw,ch here, too?
use_bitmap = memDC->m_selected;
}
/* apply mask if any */
// apply mask if any
GdkBitmap *mask = (GdkBitmap *) NULL;
if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
GdkBitmap *new_mask = (GdkBitmap*) NULL;
if (useMask && mask)
{
GdkBitmap *new_mask = (GdkBitmap*) NULL;
#ifndef __WXGTK20__ // TODO fix crash
if (!m_currentClippingRegion.IsNull())
{
GdkColor col;
@ -1317,20 +1319,22 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
col.pixel = 1;
gdk_gc_set_foreground( gc, &col );
gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
gdk_gc_set_clip_origin( gc, -xx, -yy );
// was: gdk_gc_set_clip_origin( gc, -xx, -yy );
gdk_gc_set_clip_origin( gc, -cx, -cy );
gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
gdk_gc_set_stipple( gc, mask );
gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
gdk_gc_unref( gc );
}
#endif
if (is_mono)
{
if (new_mask)
gdk_gc_set_clip_mask( m_textGC, new_mask );
else
gdk_gc_set_clip_mask( m_textGC, mask );
gdk_gc_set_clip_origin( m_textGC, xx, yy );
// was: gdk_gc_set_clip_origin( m_textGC, xx, yy );
gdk_gc_set_clip_origin( m_textGC, cx, cy );
}
else
{
@ -1338,21 +1342,39 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
gdk_gc_set_clip_mask( m_penGC, new_mask );
else
gdk_gc_set_clip_mask( m_penGC, mask );
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 );
}
if (new_mask)
gdk_bitmap_unref( new_mask );
}
/* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
drawing a mono-bitmap (XBitmap) we use the current text GC */
// Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
// drawing a mono-bitmap (XBitmap) we use the current text GC
if (is_mono)
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh );
{
#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 );
gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, cx, cy, cw, ch );
#endif
}
else
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 );
}
/* remove mask again if any */
// remove mask again if any
if (useMask && mask)
{
if (is_mono)
@ -1370,49 +1392,32 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
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))
{
/* draw source window into a bitmap as we cannot scale
a window in contrast to a bitmap. this would actually
work with memory dcs as well, but we'd lose the mask
information and waste one step in this process since
a memory already has a bitmap. all this is slightly
inefficient as we could take an XImage directly from
an X window, but we'd then also have to care that
the window is not outside the screen (in which case
we'd get a BadMatch or what not).
Is a double XGetImage and combined XGetPixel and
XPutPixel really faster? I'm not sure. look at wxXt
for a different implementation of the same problem. */
wxBitmap bitmap( width, height );
/* copy including child window contents */
gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0,
srcDC->GetWindow(),
xsrc, ysrc, width, height );
gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
/* scale image */
wxImage image = bitmap.ConvertToImage();
image = image.Scale( ww, hh );
/* convert to bitmap */
bitmap = wxBitmap(image);
/* draw scaled bitmap */
gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
// get clip coords
wxRegion tmp( xx,yy,ww,hh );
tmp.Intersect( m_currentClippingRegion );
wxCoord cx,cy,cw,ch;
tmp.GetBox(cx,cy,cw,ch);
// rescale bitmap
wxBitmap bitmap = memDC->m_selected.Rescale( cx-xx, cy-yy, cw, ch, ww, hh );
// draw scaled bitmap
// was: gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, cx, cy, -1, -1 );
}
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_window_copy_area( m_window, m_penGC, xx, yy,
srcDC->GetWindow(),
@ -1422,6 +1427,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
}
SetLogicalFunction( old_logical_func );
return TRUE;
}
@ -1457,7 +1463,7 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
int w,h;
if (m_scaleY != 1.0)
if (abs(m_scaleY - 1.0) < 0.00001)
{
// If there is a user or actually any scale applied to
// the device context, scale the font.