X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f1c72f0ca0c6577bf092aa027d153c32204e8cc5..96461cc29d03b4a7ab72abaae2e7edace93dd2a5:/src/gtk1/dcclient.cpp diff --git a/src/gtk1/dcclient.cpp b/src/gtk1/dcclient.cpp index 9879635b32..d77ba5460c 100644 --- a/src/gtk1/dcclient.cpp +++ b/src/gtk1/dcclient.cpp @@ -27,7 +27,7 @@ #include "wx/gtk/win_gtk.h" -#include // for floating-point functions +#include "wx/math.h" // for floating-point functions #include #include @@ -95,7 +95,7 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable, g_return_if_fail (drawable != NULL); g_return_if_fail (src != NULL); g_return_if_fail (gc != NULL); - + #ifdef __WXGTK20__ gint src_width, src_height; gdk_drawable_get_size(src, &src_width, &src_height); @@ -114,7 +114,7 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable, GdkWindowPrivate *drawable_private; GdkWindowPrivate *src_private; GdkGCPrivate *gc_private; - + drawable_private = (GdkWindowPrivate*) drawable; src_private = (GdkWindowPrivate*) src; if (drawable_private->destroyed || src_private->destroyed) @@ -124,10 +124,10 @@ void gdk_wx_draw_bitmap(GdkDrawable *drawable, 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, @@ -180,10 +180,10 @@ static void wxInitGCPool() // This really could wait until the first call to // wxGetPoolGC, but we will make the first allocation // now when other initialization is being performed. - + // Set initial pool size. wxGCPoolSize = GC_POOL_ALLOC_SIZE; - + // Allocate initial pool. wxGCPool = (wxGC *)malloc(wxGCPoolSize * sizeof(wxGC)); if (wxGCPool == NULL) @@ -195,7 +195,7 @@ static void wxInitGCPool() wxFAIL_MSG( wxT("Cannot allocate GC pool") ); return; } - + // Zero initial pool. memset(wxGCPool, 0, wxGCPoolSize * sizeof(wxGC)); } @@ -216,7 +216,7 @@ static void wxCleanUpGCPool() static GdkGC* wxGetPoolGC( GdkWindow *window, wxPoolGCType type ) { wxGC *pptr; - + // Look for an available GC. for (int i = 0; i < wxGCPoolSize; i++) { @@ -225,11 +225,11 @@ static GdkGC* wxGetPoolGC( GdkWindow *window, wxPoolGCType type ) wxGCPool[i].m_gc = gdk_gc_new( window ); gdk_gc_set_exposures( wxGCPool[i].m_gc, FALSE ); wxGCPool[i].m_type = type; - wxGCPool[i].m_used = FALSE; + wxGCPool[i].m_used = false; } if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type)) { - wxGCPool[i].m_used = TRUE; + wxGCPool[i].m_used = true; return wxGCPool[i].m_gc; } } @@ -244,20 +244,20 @@ static GdkGC* wxGetPoolGC( GdkWindow *window, wxPoolGCType type ) wxGCPool = pptr; memset(&wxGCPool[wxGCPoolSize], 0, GC_POOL_ALLOC_SIZE*sizeof(wxGC)); - - // Initialize entry we will return. + + // Initialize entry we will return. wxGCPool[wxGCPoolSize].m_gc = gdk_gc_new( window ); gdk_gc_set_exposures( wxGCPool[wxGCPoolSize].m_gc, FALSE ); wxGCPool[wxGCPoolSize].m_type = type; - wxGCPool[wxGCPoolSize].m_used = TRUE; - + wxGCPool[wxGCPoolSize].m_used = true; + // Set new value of pool size. wxGCPoolSize += GC_POOL_ALLOC_SIZE; - + // Return newly allocated entry. return wxGCPool[wxGCPoolSize-GC_POOL_ALLOC_SIZE].m_gc; } - + // The realloc failed. Fall through to error. wxFAIL_MSG( wxT("No GC available") ); @@ -270,7 +270,7 @@ static void wxFreePoolGC( GdkGC *gc ) { if (wxGCPool[i].m_gc == gc) { - wxGCPool[i].m_used = FALSE; + wxGCPool[i].m_used = false; return; } } @@ -291,8 +291,8 @@ wxWindowDC::wxWindowDC() m_textGC = (GdkGC *) NULL; m_bgGC = (GdkGC *) NULL; m_cmap = (GdkColormap *) NULL; - m_isMemDC = FALSE; - m_isScreenDC = FALSE; + m_isMemDC = false; + m_isScreenDC = false; m_owner = (wxWindow *)NULL; #ifdef __WXGTK20__ m_context = (PangoContext *)NULL; @@ -311,8 +311,8 @@ wxWindowDC::wxWindowDC( wxWindow *window ) m_bgGC = (GdkGC *) NULL; m_cmap = (GdkColormap *) NULL; m_owner = (wxWindow *)NULL; - m_isMemDC = FALSE; - m_isScreenDC = FALSE; + m_isMemDC = false; + m_isScreenDC = false; m_font = window->GetFont(); GtkWidget *widget = window->m_wxwindow; @@ -341,7 +341,7 @@ wxWindowDC::wxWindowDC( wxWindow *window ) if (!m_window) { // Don't report problems as per MSW. - m_ok = TRUE; + m_ok = true; return; } @@ -363,7 +363,7 @@ wxWindowDC::wxWindowDC( wxWindow *window ) wxWindowDC::~wxWindowDC() { Destroy(); - + #ifdef __WXGTK20__ if (m_layout) g_object_unref( G_OBJECT( m_layout ) ); @@ -374,7 +374,7 @@ wxWindowDC::~wxWindowDC() void wxWindowDC::SetUpDC() { - m_ok = TRUE; + m_ok = true; wxASSERT_MSG( !m_penGC, wxT("GCs already created") ); @@ -465,7 +465,7 @@ void wxWindowDC::DoGetSize( int* width, int* height ) const m_owner->GetSize(width, height); } -extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, +extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, const wxColour & col, int style); bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y, @@ -486,7 +486,7 @@ bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const wxImage image = bitmap.ConvertToImage(); col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0)); - return TRUE; + return true; } void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) @@ -700,7 +700,7 @@ void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord return; } - for (int i = 0; i < n; i++) + for (int i = 0; i < n; i++) { wxCoord x1 = XLOG2DEV(points[i].x + xoffset); wxCoord y1 = YLOG2DEV(points[i].y + yoffset); @@ -784,7 +784,7 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoor } */ gdk_draw_polygon( m_window, m_penGC, FALSE, gdkpoints, n ); - + } } @@ -1038,7 +1038,7 @@ void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord hei void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y ) { // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why - DoDrawBitmap( (const wxBitmap&)icon, x, y, (bool)TRUE ); + DoDrawBitmap( (const wxBitmap&)icon, x, y, true ); } void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, @@ -1075,11 +1075,11 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, return; } - // scale bitmap if required + // scale bitmap if required wxBitmap use_bitmap = bitmap; if ((w != ww) || (h != hh)) use_bitmap = use_bitmap.Rescale( 0, 0, ww, hh, ww, hh ); - + #if !GTK_CHECK_VERSION(2,2,0) // NB: We can't render pixbufs with GTK+ < 2.2, we need to use pixmaps code. // Pixbufs-based bitmaps with alpha channel don't have a mask, so we @@ -1087,13 +1087,13 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, // and also creates the mask as a side-effect: use_bitmap.GetPixmap(); #endif - + // 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) { if (!m_currentClippingRegion.IsNull()) @@ -1115,7 +1115,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh ); gdk_gc_unref( gc ); } - + if (is_mono) { if (new_mask) @@ -1144,9 +1144,9 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &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 @@ -1190,7 +1190,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); } } - + if (new_mask) gdk_bitmap_unref( new_mask ); } @@ -1203,11 +1203,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, bool useMask, wxCoord xsrcMask, wxCoord ysrcMask ) { - 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; // transform the source DC coords to the device ones xsrc = source->XLOG2DEV(xsrc); @@ -1216,8 +1216,8 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxClientDC *srcDC = (wxClientDC*)source; wxMemoryDC *memDC = (wxMemoryDC*)source; - bool use_bitmap_method = FALSE; - bool is_mono = FALSE; + bool use_bitmap_method = false; + bool is_mono = false; // TODO: use the mask origin when drawing transparently if (xsrcMask == -1 && ysrcMask == -1) @@ -1228,7 +1228,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, if (srcDC->m_isMemDC) { - if (!memDC->m_selected.Ok()) return FALSE; + if (!memDC->m_selected.Ok()) return false; is_mono = (memDC->m_selected.GetDepth() == 1); @@ -1243,14 +1243,14 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, // 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; + use_bitmap_method = true; } 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 - use_bitmap_method = TRUE; + use_bitmap_method = true; } else if ((xsrc == 0) && (ysrc == 0) && (width == memDC->m_selected.GetWidth()) && @@ -1260,11 +1260,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, // 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; + use_bitmap_method = true; } else { - use_bitmap_method = FALSE; + use_bitmap_method = false; } } @@ -1284,7 +1284,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxRegion tmp( xx,yy,ww,hh ); tmp.Intersect( m_currentClippingRegion ); if (tmp.IsEmpty()) - return TRUE; + return true; } int old_logical_func = m_logicalFunction; @@ -1304,7 +1304,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord cy = yy; wxCoord cw = ww; wxCoord ch = hh; - + // interpret userscale of src too double xsc,ysc; memDC->GetUserScale(&xsc,&ysc); @@ -1324,7 +1324,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, 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); } @@ -1339,7 +1339,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); GdkBitmap *new_mask = (GdkBitmap*) NULL; - + if (useMask && mask) { if (!m_currentClippingRegion.IsNull()) @@ -1394,9 +1394,9 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, 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 @@ -1428,7 +1428,7 @@ 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 ); } @@ -1441,8 +1441,8 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, tmp.Intersect( m_currentClippingRegion ); wxCoord cx,cy,cw,ch; tmp.GetBox(cx,cy,cw,ch); - - // rescale bitmap + + // rescale bitmap wxBitmap bitmap = memDC->m_selected.Rescale( cx-xx, cy-yy, cw, ch, ww, hh ); // draw scaled bitmap @@ -1451,7 +1451,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, } 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 gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS ); @@ -1463,8 +1463,8 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, } SetLogicalFunction( old_logical_func ); - - return TRUE; + + return true; } void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) @@ -1472,7 +1472,7 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) wxCHECK_RET( Ok(), wxT("invalid window dc") ); if (!m_window) return; - + if (text.empty()) return; #ifndef __WXGTK20__ @@ -1501,7 +1501,7 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) #endif size_t datalen = strlen((const char*)data); pango_layout_set_text( m_layout, (const char*) data, datalen); - + if (underlined) { PangoAttrList *attrs = pango_attr_list_new(); @@ -1519,16 +1519,16 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) { // If there is a user or actually any scale applied to // the device context, scale the font. - + // scale font description gint oldSize = pango_font_description_get_size( m_fontdesc ); double size = oldSize; size = size * m_scaleY; pango_font_description_set_size( m_fontdesc, (gint)size ); - + // actually apply scaled font pango_layout_set_font_description( m_layout, m_fontdesc ); - + pango_layout_get_pixel_size( m_layout, &w, &h ); if ( m_backgroundMode == wxSOLID ) { @@ -1536,13 +1536,13 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h); gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); } - + // Draw layout. gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); - + // reset unscaled size pango_font_description_set_size( m_fontdesc, oldSize ); - + // actually apply unscaled font pango_layout_set_font_description( m_layout, m_fontdesc ); } @@ -1564,10 +1564,10 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) // undo underline attributes setting: pango_layout_set_attributes(m_layout, NULL); } - + wxCoord width = w; wxCoord height = h; - + #else // GTK+ 1.x wxCoord width = gdk_string_width( font, text.mbc_str() ); wxCoord height = font->ascent + font->descent; @@ -1620,7 +1620,7 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, #ifdef __WXGTK20__ // implement later without GdkFont for GTK 2.0 GetTextExtent(text, &w, &h, NULL,NULL, &m_font); - + #else GdkFont *font = m_font.GetInternalFont( m_scaleY ); @@ -1655,7 +1655,7 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, y4 = h*dx; double x3 = x4 + x2, y3 = y4 + y2; - + // calc max and min wxCoord maxX = (wxCoord)(dmax(x2, dmax(x3, x4)) + 0.5), maxY = (wxCoord)(dmax(y2, dmax(y3, y4)) + 0.5), @@ -1669,9 +1669,32 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, m_textForegroundColour.Green(), m_textForegroundColour.Blue() ); image = image.Rotate( rad, wxPoint(0,0) ); - + + int i_angle = (int) angle; + i_angle = i_angle % 360; + if (i_angle < 0) + i_angle += 360; + int xoffset = 0; + if ((i_angle >= 90.0) && (i_angle < 270.0)) + xoffset = image.GetWidth(); + int yoffset = 0; + if ((i_angle >= 0.0) && (i_angle < 180.0)) + yoffset = image.GetHeight(); + + if ((i_angle >= 0) && (i_angle < 90)) + yoffset -= (int)( cos(rad)*h ); + if ((i_angle >= 90) && (i_angle < 180)) + xoffset -= (int)( sin(rad)*h ); + if ((i_angle >= 180) && (i_angle < 270)) + yoffset -= (int)( cos(rad)*h ); + if ((i_angle >= 270) && (i_angle < 360)) + xoffset -= (int)( sin(rad)*h ); + + int i_x = x - xoffset; + int i_y = y - yoffset; + src = image; - DoDrawBitmap( src, x /*- (int)(sin(rad)*h)*/ , y-image.GetHeight()+h, true ); + DoDrawBitmap( src, i_x, i_y, true ); // it would be better to draw with non underlined font and draw the line @@ -1704,16 +1727,16 @@ void wxWindowDC::DoGetTextExtent(const wxString &string, if ( externalLeading ) *externalLeading = 0; - if (string.IsEmpty()) + if (string.empty()) { return; } - + #ifdef __WXGTK20__ // Set new font description if (theFont) pango_layout_set_font_description( m_layout, theFont->GetNativeFontInfo()->description ); - + // Set layout's text #if wxUSE_UNICODE const wxCharBuffer data = wxConvUTF8.cWC2MB( string ); @@ -1737,12 +1760,12 @@ void wxWindowDC::DoGetTextExtent(const wxString &string, } pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) ); - + int w,h; pango_layout_get_pixel_size( m_layout, &w, &h ); - + if (width) - *width = (wxCoord) w; + *width = (wxCoord) w; if (height) *height = (wxCoord) h; if (descent) @@ -1752,7 +1775,7 @@ void wxWindowDC::DoGetTextExtent(const wxString &string, pango_layout_iter_free(iter); *descent = h - PANGO_PIXELS(baseline); } - + // Reset old font description if (theFont) pango_layout_set_font_description( m_layout, m_fontdesc ); @@ -1760,7 +1783,7 @@ void wxWindowDC::DoGetTextExtent(const wxString &string, wxFont fontToUse = m_font; if (theFont) fontToUse = *theFont; - + GdkFont *font = fontToUse.GetInternalFont( m_scaleY ); if ( !font ) return; @@ -1845,39 +1868,39 @@ void wxWindowDC::Clear() void wxWindowDC::SetFont( const wxFont &font ) { m_font = font; - + #ifdef __WXGTK20__ if (m_font.Ok()) { if (m_fontdesc) pango_font_description_free( m_fontdesc ); - + m_fontdesc = pango_font_description_copy( m_font.GetNativeFontInfo()->description ); - - + + if (m_owner) { PangoContext *oldContext = m_context; - + // We might want to use the X11 context for faster // rendering on screen if (m_font.GetNoAntiAliasing()) m_context = m_owner->GtkGetPangoX11Context(); else m_context = m_owner->GtkGetPangoDefaultContext(); - + // If we switch back/forth between different contexts // we also have to create a new layout. I think so, - // at least, and it doesn't hurt to do it. + // at least, and it doesn't hurt to do it. if (oldContext != m_context) { if (m_layout) g_object_unref( G_OBJECT( m_layout ) ); - + m_layout = pango_layout_new( m_context ); } } - + pango_layout_set_font_description( m_layout, m_fontdesc ); } #endif @@ -2072,7 +2095,7 @@ void wxWindowDC::SetBrush( const wxBrush &brush ) gdk_gc_set_stipple( m_textGC, m_brush.GetStipple()->GetMask()->GetBitmap() ); } - if (IS_HATCH(m_brush.GetStyle())) + if (m_brush.IsHatch()) { gdk_gc_set_fill( m_brushGC, GDK_STIPPLED ); int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH; @@ -2117,7 +2140,7 @@ void wxWindowDC::SetBackground( const wxBrush &brush ) } } - if (IS_HATCH(m_backgroundBrush.GetStyle())) + if (m_backgroundBrush.IsHatch()) { gdk_gc_set_fill( m_bgGC, GDK_STIPPLED ); int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH; @@ -2410,7 +2433,7 @@ wxPaintDC::wxPaintDC( wxWindow *win ) wxSize sz = win->GetSize(); m_paintClippingRegion = win->GetUpdateRegion(); wxLimitRegionToSize(m_paintClippingRegion, sz); - + GdkRegion *region = m_paintClippingRegion.GetRegion(); if ( region ) { @@ -2473,7 +2496,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) bool wxDCModule::OnInit() { wxInitGCPool(); - return TRUE; + return true; } void wxDCModule::OnExit()