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__
- 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,
// If we cannot malloc, then fail with error
// when debug is enabled. If debug is not enabled,
// the problem will eventually get caught
- // in wxGetPoolGC.
+ // in wxGetPoolGC.
wxFAIL_MSG( wxT("Cannot allocate GC pool") );
return;
}
// We did not find an available GC.
// We need to grow the GC pool.
pptr = (wxGC *)realloc(wxGCPool,
- (wxGCPoolSize + GC_POOL_ALLOC_SIZE)*sizeof(wxGC));
+ (wxGCPoolSize + GC_POOL_ALLOC_SIZE)*sizeof(wxGC));
if (pptr != NULL)
{
// Initialize newly allocated pool.
wxGCPool = pptr;
- memset(&wxGCPool[wxGCPoolSize], 0,
- GC_POOL_ALLOC_SIZE*sizeof(wxGC));
+ memset(&wxGCPool[wxGCPoolSize], 0,
+ GC_POOL_ALLOC_SIZE*sizeof(wxGC));
// Initialize entry we will return.
wxGCPool[wxGCPoolSize].m_gc = gdk_gc_new( window );
bool is_mono = (bitmap.GetBitmap() != NULL);
- /* scale/translate size and position */
+ // scale/translate size and position
int xx = XLOG2DEV(x);
int yy = YLOG2DEV(y);
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 );
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 );
- }
+ 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
- {
- 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 );
- }
-
+ gdk_gc_set_clip_mask( m_textGC, mask );
+ gdk_gc_set_clip_origin( m_textGC, xx, yy );
+ }
+ else
+ {
if (new_mask)
- gdk_bitmap_unref( 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)
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 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;
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
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 );
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 for the bitmap. If we don't
+ // use wxBitmap::Rescale(), which can clip the
+ // bitmap, these are the same as the original
+ // coordinates
+ wxCoord cx = xx;
+ wxCoord cy = yy;
+ wxCoord cw = ww;
+ wxCoord ch = hh;
+
+ // 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);
+ // This indicates that the blitting code below will get
+ // a clipped bitmap and therefore needs to move the origin
+ // accordingly
+ wxRegion tmp( xx,yy,ww,hh );
+ tmp.Intersect( m_currentClippingRegion );
+ tmp.GetBox(cx,cy,cw,ch);
+
+ // Scale and clipped bitmap
+ use_bitmap = memDC->m_selected.Rescale(cx-xx,cy-yy,cw,ch,bm_ww,bm_hh);
}
else
{
+ // Don't scale bitmap
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;
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
{
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)
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(),
}
SetLogicalFunction( old_logical_func );
+
return TRUE;
}
int w,h;
- if (m_scaleY != 1.0)
+ if (fabs(m_scaleY - 1.0) < 0.00001)
{
// If there is a user or actually any scale applied to
// the device context, scale the font.
( fabs((double) XLOG2DEVREL(width)) +
fabs((double) YLOG2DEVREL(width)) ) / 2.0;
width = (int)w;
+ if ( !width )
+ {
+ // width can't be 0 or an internal GTK error occurs inside
+ // gdk_gc_set_dashes() below
+ width = 1;
+ }
}
static const wxGTKDash dotted[] = {1, 1};