From 01111366c9b4ea40eee7f4b13ddfe6f6b9f886db Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Sat, 24 Oct 1998 17:12:05 +0000 Subject: [PATCH] Removed usage of GdkImlib Added platform independent wxImage class Changed wxBitmap and wxImageList accordingly Correctted header text git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@905 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gtk/accel.h | 2 +- include/wx/gtk/app.h | 2 +- include/wx/gtk/bitmap.h | 14 +- include/wx/gtk/bmpbuttn.h | 5 +- include/wx/gtk/brush.h | 5 +- include/wx/gtk/button.h | 5 +- include/wx/gtk/checkbox.h | 5 +- include/wx/gtk/choice.h | 5 +- include/wx/gtk/colour.h | 5 +- include/wx/gtk1/accel.h | 2 +- include/wx/gtk1/app.h | 2 +- include/wx/gtk1/bitmap.h | 14 +- include/wx/gtk1/bmpbuttn.h | 5 +- include/wx/gtk1/brush.h | 5 +- include/wx/gtk1/button.h | 5 +- include/wx/gtk1/checkbox.h | 5 +- include/wx/gtk1/choice.h | 5 +- include/wx/gtk1/colour.h | 5 +- include/wx/image.h | 162 +++++++ samples/image/Makefile | 1 + samples/image/Makefile.in | 26 ++ samples/image/horse.png | Bin 0 -> 68852 bytes samples/image/image.cpp | 158 +++++++ src/Makefile.in | 5 +- src/common/image.cpp | 898 +++++++++++++++++++++++++++++++++++++ src/generic/imaglist.cpp | 29 +- src/gtk.inc | 10 +- src/gtk/app.cpp | 100 ++++- src/gtk/bitmap.cpp | 361 +++++++-------- src/gtk/bmpbuttn.cpp | 5 +- src/gtk/brush.cpp | 5 +- src/gtk/button.cpp | 5 +- src/gtk/checkbox.cpp | 5 +- src/gtk/choice.cpp | 5 +- src/gtk/colour.cpp | 39 +- src/gtk/combobox.cpp | 5 +- src/gtk/control.cpp | 5 +- src/gtk/cursor.cpp | 5 +- src/gtk/data.cpp | 3 +- src/gtk/dc.cpp | 1 - src/gtk/dcclient.cpp | 35 +- src/gtk/dcmemory.cpp | 19 +- src/gtk/dcscreen.cpp | 5 +- src/gtk/dialog.cpp | 5 +- src/gtk/dnd.cpp | 5 +- src/gtk/filedlg.cpp | 5 +- src/gtk/font.cpp | 3 +- src/gtk/frame.cpp | 5 +- src/gtk/gauge.cpp | 5 +- src/gtk/notebook.cpp | 5 +- src/gtk/timer.cpp | 5 +- src/gtk/utilsgtk.cpp | 1 - src/gtk/win_gtk.c | 7 +- src/gtk/window.cpp | 5 +- src/gtk1/app.cpp | 100 ++++- src/gtk1/bitmap.cpp | 361 +++++++-------- src/gtk1/bmpbuttn.cpp | 5 +- src/gtk1/brush.cpp | 5 +- src/gtk1/button.cpp | 5 +- src/gtk1/checkbox.cpp | 5 +- src/gtk1/choice.cpp | 5 +- src/gtk1/colour.cpp | 39 +- src/gtk1/combobox.cpp | 5 +- src/gtk1/control.cpp | 5 +- src/gtk1/cursor.cpp | 5 +- src/gtk1/data.cpp | 3 +- src/gtk1/dc.cpp | 1 - src/gtk1/dcclient.cpp | 35 +- src/gtk1/dcmemory.cpp | 19 +- src/gtk1/dcscreen.cpp | 5 +- src/gtk1/dialog.cpp | 5 +- src/gtk1/dnd.cpp | 5 +- src/gtk1/filedlg.cpp | 5 +- src/gtk1/font.cpp | 3 +- src/gtk1/frame.cpp | 5 +- src/gtk1/gauge.cpp | 5 +- src/gtk1/notebook.cpp | 5 +- src/gtk1/timer.cpp | 5 +- src/gtk1/utilsgtk.cpp | 1 - src/gtk1/win_gtk.c | 7 +- src/gtk1/window.cpp | 5 +- 81 files changed, 1925 insertions(+), 768 deletions(-) create mode 100644 include/wx/image.h create mode 100644 samples/image/Makefile create mode 100644 samples/image/Makefile.in create mode 100644 samples/image/horse.png create mode 100644 samples/image/image.cpp create mode 100644 src/common/image.cpp diff --git a/include/wx/gtk/accel.h b/include/wx/gtk/accel.h index 3f7ce4056e..9b2f0e69d0 100644 --- a/include/wx/gtk/accel.h +++ b/include/wx/gtk/accel.h @@ -3,7 +3,7 @@ // Purpose: wxAcceleratorTable class // Author: Robert // Modified by: -// RCS-ID: +// RCS-ID: $id$ // Copyright: (c) Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk/app.h b/include/wx/gtk/app.h index 53f89a2abe..2df05b4886 100644 --- a/include/wx/gtk/app.h +++ b/include/wx/gtk/app.h @@ -4,7 +4,7 @@ // Author: Robert Roebling // Created: 01/02/97 // Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling, Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk/bitmap.h b/include/wx/gtk/bitmap.h index 81406d49ec..15af99d2c5 100644 --- a/include/wx/gtk/bitmap.h +++ b/include/wx/gtk/bitmap.h @@ -2,9 +2,8 @@ // Name: bitmap.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -20,6 +19,7 @@ #include "wx/object.h" #include "wx/string.h" #include "wx/palette.h" +#include "wx/image.h" //----------------------------------------------------------------------------- // classes @@ -60,7 +60,6 @@ class wxMask: public wxObject // wxBitmap //----------------------------------------------------------------------------- -// CMB 20/5/98: added xbm constructor and GetBitmap() method class wxBitmap: public wxObject { DECLARE_DYNAMIC_CLASS(wxBitmap) @@ -70,6 +69,7 @@ class wxBitmap: public wxObject wxBitmap(); wxBitmap( int width, int height, int depth = -1 ); wxBitmap( const char bits[], int width, int height, int depth = 1 ); + wxBitmap( const wxImage &image ); wxBitmap( char **bits ); wxBitmap( const wxBitmap& bmp ); wxBitmap( const wxBitmap* bmp ); @@ -79,6 +79,8 @@ class wxBitmap: public wxObject bool operator == ( const wxBitmap& bmp ); bool operator != ( const wxBitmap& bmp ); bool Ok() const; + + wxImage ConvertToImage() const; int GetHeight() const; int GetWidth() const; @@ -90,8 +92,6 @@ class wxBitmap: public wxObject wxMask *GetMask() const; void SetMask( wxMask *mask ); - void Resize( int height, int width ); - bool SaveFile( const wxString &name, int type, wxPalette *palette = (wxPalette *) NULL ); bool LoadFile( const wxString &name, int type = wxBITMAP_TYPE_XPM); @@ -104,10 +104,6 @@ class wxBitmap: public wxObject GdkPixmap *GetPixmap() const; GdkBitmap *GetBitmap() const; - void DestroyImage(); - void RecreateImage(); - void Render(); - // no data :-) }; diff --git a/include/wx/gtk/bmpbuttn.h b/include/wx/gtk/bmpbuttn.h index 6800d97bf4..5d61d0708b 100644 --- a/include/wx/gtk/bmpbuttn.h +++ b/include/wx/gtk/bmpbuttn.h @@ -2,9 +2,8 @@ // Name: bmpbutton.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk/brush.h b/include/wx/gtk/brush.h index 66a3d451d5..8a9fd41bf4 100644 --- a/include/wx/gtk/brush.h +++ b/include/wx/gtk/brush.h @@ -2,9 +2,8 @@ // Name: brush.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk/button.h b/include/wx/gtk/button.h index bbc5f130e2..bfabb1d0be 100644 --- a/include/wx/gtk/button.h +++ b/include/wx/gtk/button.h @@ -2,9 +2,8 @@ // Name: button.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk/checkbox.h b/include/wx/gtk/checkbox.h index d83a8d59ea..f2027e494b 100644 --- a/include/wx/gtk/checkbox.h +++ b/include/wx/gtk/checkbox.h @@ -2,9 +2,8 @@ // Name: checkbox.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk/choice.h b/include/wx/gtk/choice.h index 9929a37fef..40cecba786 100644 --- a/include/wx/gtk/choice.h +++ b/include/wx/gtk/choice.h @@ -2,9 +2,8 @@ // Name: choice.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk/colour.h b/include/wx/gtk/colour.h index da8e9ee208..77e4155350 100644 --- a/include/wx/gtk/colour.h +++ b/include/wx/gtk/colour.h @@ -2,9 +2,8 @@ // Name: colour.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk1/accel.h b/include/wx/gtk1/accel.h index 3f7ce4056e..9b2f0e69d0 100644 --- a/include/wx/gtk1/accel.h +++ b/include/wx/gtk1/accel.h @@ -3,7 +3,7 @@ // Purpose: wxAcceleratorTable class // Author: Robert // Modified by: -// RCS-ID: +// RCS-ID: $id$ // Copyright: (c) Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk1/app.h b/include/wx/gtk1/app.h index 53f89a2abe..2df05b4886 100644 --- a/include/wx/gtk1/app.h +++ b/include/wx/gtk1/app.h @@ -4,7 +4,7 @@ // Author: Robert Roebling // Created: 01/02/97 // Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling, Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk1/bitmap.h b/include/wx/gtk1/bitmap.h index 81406d49ec..15af99d2c5 100644 --- a/include/wx/gtk1/bitmap.h +++ b/include/wx/gtk1/bitmap.h @@ -2,9 +2,8 @@ // Name: bitmap.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -20,6 +19,7 @@ #include "wx/object.h" #include "wx/string.h" #include "wx/palette.h" +#include "wx/image.h" //----------------------------------------------------------------------------- // classes @@ -60,7 +60,6 @@ class wxMask: public wxObject // wxBitmap //----------------------------------------------------------------------------- -// CMB 20/5/98: added xbm constructor and GetBitmap() method class wxBitmap: public wxObject { DECLARE_DYNAMIC_CLASS(wxBitmap) @@ -70,6 +69,7 @@ class wxBitmap: public wxObject wxBitmap(); wxBitmap( int width, int height, int depth = -1 ); wxBitmap( const char bits[], int width, int height, int depth = 1 ); + wxBitmap( const wxImage &image ); wxBitmap( char **bits ); wxBitmap( const wxBitmap& bmp ); wxBitmap( const wxBitmap* bmp ); @@ -79,6 +79,8 @@ class wxBitmap: public wxObject bool operator == ( const wxBitmap& bmp ); bool operator != ( const wxBitmap& bmp ); bool Ok() const; + + wxImage ConvertToImage() const; int GetHeight() const; int GetWidth() const; @@ -90,8 +92,6 @@ class wxBitmap: public wxObject wxMask *GetMask() const; void SetMask( wxMask *mask ); - void Resize( int height, int width ); - bool SaveFile( const wxString &name, int type, wxPalette *palette = (wxPalette *) NULL ); bool LoadFile( const wxString &name, int type = wxBITMAP_TYPE_XPM); @@ -104,10 +104,6 @@ class wxBitmap: public wxObject GdkPixmap *GetPixmap() const; GdkBitmap *GetBitmap() const; - void DestroyImage(); - void RecreateImage(); - void Render(); - // no data :-) }; diff --git a/include/wx/gtk1/bmpbuttn.h b/include/wx/gtk1/bmpbuttn.h index 6800d97bf4..5d61d0708b 100644 --- a/include/wx/gtk1/bmpbuttn.h +++ b/include/wx/gtk1/bmpbuttn.h @@ -2,9 +2,8 @@ // Name: bmpbutton.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk1/brush.h b/include/wx/gtk1/brush.h index 66a3d451d5..8a9fd41bf4 100644 --- a/include/wx/gtk1/brush.h +++ b/include/wx/gtk1/brush.h @@ -2,9 +2,8 @@ // Name: brush.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk1/button.h b/include/wx/gtk1/button.h index bbc5f130e2..bfabb1d0be 100644 --- a/include/wx/gtk1/button.h +++ b/include/wx/gtk1/button.h @@ -2,9 +2,8 @@ // Name: button.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk1/checkbox.h b/include/wx/gtk1/checkbox.h index d83a8d59ea..f2027e494b 100644 --- a/include/wx/gtk1/checkbox.h +++ b/include/wx/gtk1/checkbox.h @@ -2,9 +2,8 @@ // Name: checkbox.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk1/choice.h b/include/wx/gtk1/choice.h index 9929a37fef..40cecba786 100644 --- a/include/wx/gtk1/choice.h +++ b/include/wx/gtk1/choice.h @@ -2,9 +2,8 @@ // Name: choice.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/gtk1/colour.h b/include/wx/gtk1/colour.h index da8e9ee208..77e4155350 100644 --- a/include/wx/gtk1/colour.h +++ b/include/wx/gtk1/colour.h @@ -2,9 +2,8 @@ // Name: colour.h // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/include/wx/image.h b/include/wx/image.h new file mode 100644 index 0000000000..dd8a5e9754 --- /dev/null +++ b/include/wx/image.h @@ -0,0 +1,162 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: image.h +// Purpose: wxImage class +// Author: Robert Roebling +// RCS-ID: $Id$ +// Copyright: (c) Robert Roebling +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_IMAGE_H_ +#define _WX_IMAGE_H_ + +#ifdef __GNUG__ +#pragma interface "image.h" +#endif + +#include "wx/setup.h" +#include "wx/object.h" +#include "wx/string.h" +#include "wx/gdicmn.h" + +//----------------------------------------------------------------------------- +// classes +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxImageHandler; +class WXDLLEXPORT wxPNGHandler; +class WXDLLEXPORT wxBMPHandler; +class WXDLLEXPORT wxImage; + +//----------------------------------------------------------------------------- +// wxImageHandler +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxImageHandler: public wxObject +{ + DECLARE_DYNAMIC_CLASS(wxImageHandler) + +public: + wxImageHandler() { m_name = ""; m_extension = ""; m_type = 0; } + + virtual bool LoadFile( wxImage *image, const wxString& name ); + virtual bool SaveFile( wxImage *image, const wxString& name ); + + inline void SetName(const wxString& name) { m_name = name; } + inline void SetExtension(const wxString& ext) { m_extension = ext; } + inline void SetType(long type) { m_type = type; } + inline wxString GetName() const { return m_name; } + inline wxString GetExtension() const { return m_extension; } + inline long GetType() const { return m_type; } + +protected: + wxString m_name; + wxString m_extension; + long m_type; + +}; + +//----------------------------------------------------------------------------- +// wxPNGHandler +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxPNGHandler: public wxImageHandler +{ + DECLARE_DYNAMIC_CLASS(wxPNGHandler) + +public: + + inline wxPNGHandler() + { + m_name = "PNG file"; + m_extension = "png"; + m_type = wxBITMAP_TYPE_PNG; + }; + + virtual bool LoadFile( wxImage *image, const wxString& name ); + virtual bool SaveFile( wxImage *image, const wxString& name ); +}; + +//----------------------------------------------------------------------------- +// wxBMPHandler +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxBMPHandler: public wxImageHandler +{ + DECLARE_DYNAMIC_CLASS(wxBMPHandler) + +public: + + inline wxBMPHandler() + { + m_name = "BMP file"; + m_extension = "bmp"; + m_type = wxBITMAP_TYPE_BMP; + }; + + virtual bool LoadFile( wxImage *image, const wxString& name ); +}; +//----------------------------------------------------------------------------- +// wxImage +//----------------------------------------------------------------------------- + +class WXDLLEXPORT wxImage: public wxObject +{ + DECLARE_DYNAMIC_CLASS(wxImage) + + friend class WXDLLEXPORT wxImageHandler; + +public: + + wxImage(); + wxImage( int width, int height ); + wxImage( const wxString& name, long type = wxBITMAP_TYPE_PNG ); + + wxImage( const wxImage& image ); + wxImage( const wxImage* image ); + + void Create( int width, int height ); + void Destroy(); + + virtual bool LoadFile( const wxString& name, long type = wxBITMAP_TYPE_PNG ); + virtual bool SaveFile( const wxString& name, int type ); + + bool Ok() const; + int GetWidth() const; + int GetHeight() const; + + char unsigned *GetData() const; + void SetData( char unsigned *data ); + + void SetMaskColour( unsigned char r, unsigned char g, unsigned char b ); + unsigned char GetMaskRed() const; + unsigned char GetMaskGreen() const; + unsigned char GetMaskBlue() const; + void SetMask( bool mask = TRUE ); + bool HasMask() const; + + inline wxImage& operator = (const wxImage& image) + { if (*this == image) return (*this); Ref(image); return *this; } + inline bool operator == (const wxImage& image) + { return m_refData == image.m_refData; } + inline bool operator != (const wxImage& image) + { return m_refData != image.m_refData; } + + static inline wxList& GetHandlers() { return sm_handlers; } + static void AddHandler( wxImageHandler *handler ); + static void InsertHandler( wxImageHandler *handler ); + static bool RemoveHandler( const wxString& name ); + static wxImageHandler *FindHandler( const wxString& name ); + static wxImageHandler *FindHandler( const wxString& extension, long imageType ); + static wxImageHandler *FindHandler( long imageType ); + + static void CleanUpHandlers(); + +protected: + + static wxList sm_handlers; + +}; + +#endif + // _WX_IMAGE_H_ diff --git a/samples/image/Makefile b/samples/image/Makefile new file mode 100644 index 0000000000..bccce53f76 --- /dev/null +++ b/samples/image/Makefile @@ -0,0 +1 @@ +include ../../setup/general/makeapp diff --git a/samples/image/Makefile.in b/samples/image/Makefile.in new file mode 100644 index 0000000000..d8cbc50a2a --- /dev/null +++ b/samples/image/Makefile.in @@ -0,0 +1,26 @@ +# WXXT base directory +WXBASEDIR=@WXBASEDIR@ + +# set the OS type for compilation +OS=@OS@ +# compile a library only +RULE=bin + +# define library name +BIN_TARGET=image +# define library sources +BIN_SRC=\ +image.cpp + +#define library objects +BIN_OBJ=\ +image.o + +# additional things needed to link +BIN_LINK= + +# additional things needed to compile +ADD_COMPILE= + +# include the definitions now +include ../../../template.mak diff --git a/samples/image/horse.png b/samples/image/horse.png new file mode 100644 index 0000000000000000000000000000000000000000..a9cd2a354faf1eff4efbd3ff3e2e75ebae295006 GIT binary patch literal 68852 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 ID_ABOUT, "About.."); + file_menu->Append( ID_QUIT, "Exit"); + + wxMenuBar *menu_bar = new wxMenuBar(); + menu_bar->Append(file_menu, "File"); + menu_bar->Show( TRUE ); + + SetMenuBar( menu_bar ); + + m_canvas = new MyCanvas( this, -1, wxPoint(2,62), wxSize(300-4,120-4) ); + m_canvas->SetScrollbars( 10, 10, 50, 50 ); +} + +void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) ) +{ + Close( TRUE ); +} + +void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) ) +{ + (void) wxMessageBox( "Image demo\nRobert Roebling (c) 1998", "About Image Demo", wxOK ); +} + +//----------------------------------------------------------------------------- +// MyApp +//----------------------------------------------------------------------------- + +MyApp::MyApp(void) : + wxApp( ) +{ +} + +bool MyApp::OnInit(void) +{ + wxImage::AddHandler( new wxPNGHandler ); + + wxFrame *frame = new MyFrame(); + frame->Show( TRUE ); + + return TRUE; +} + + + + + diff --git a/src/Makefile.in b/src/Makefile.in index 5caeef4a46..7ec517ec58 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -39,7 +39,6 @@ all:: @if test ! -d generic; then mkdir generic; fi @if test ! -d png; then mkdir png; fi @if test ! -d zlib; then mkdir zlib; fi - @if test ! -d gdk_imlib; then mkdir gdk_imlib; fi @if test ! -d iodbc; then mkdir iodbc; fi install:: @@ -118,13 +117,11 @@ clean:: $(RM) -rf generic $(RM) -rf png $(RM) -rf zlib - $(RM) -rf gdk_imlib $(RM) -rf iodbc @$(RM) lexer.c parser.c #additional things needed for compile -ADD_COMPILE= \ - -DHAVE_LIBPNG -DDJPEG_PROG=\"\" -DCJPEG_PROG=\"\" +ADD_COMPILE= # include the definitions now include ../../template.mak diff --git a/src/common/image.cpp b/src/common/image.cpp new file mode 100644 index 0000000000..dae0abc86c --- /dev/null +++ b/src/common/image.cpp @@ -0,0 +1,898 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: image.cpp +// Purpose: wxImage +// Author: Robert Roebling +// RCS-ID: $Id$ +// Copyright: (c) Robert Roebling +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "image.h" +#endif + +#include "wx/image.h" +#include "wx/debug.h" +#include "wx/log.h" +#include "../png/png.h" + +//----------------------------------------------------------------------------- +// wxImage +//----------------------------------------------------------------------------- + +class wxImageRefData: public wxObjectRefData +{ + public: + + wxImageRefData(void); + ~wxImageRefData(void); + + int m_width; + int m_height; + unsigned char *m_data; + bool m_hasMask; + unsigned char m_maskRed,m_maskGreen,m_maskBlue; + bool m_ok; +}; + +wxImageRefData::wxImageRefData(void) +{ + m_width = 0; + m_height = 0; + m_data = (unsigned char*) NULL; + m_ok = FALSE; + m_maskRed = 0; + m_maskGreen = 0; + m_maskBlue = 0; + m_hasMask = FALSE; +} + +wxImageRefData::~wxImageRefData(void) +{ + if (m_data) free( m_data ); +} + +wxList wxImage::sm_handlers; + +//----------------------------------------------------------------------------- + +#define M_IMGDATA ((wxImageRefData *)m_refData) + +#if !USE_SHARED_LIBRARIES +IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject) +#endif + +wxImage::wxImage() +{ +} + +wxImage::wxImage( int width, int height ) +{ + Create( width, height ); +} + +wxImage::wxImage( const wxString& name, long type ) +{ + LoadFile( name, type ); +} + +wxImage::wxImage( const wxImage& image ) +{ + Ref(image); +} + +wxImage::wxImage( const wxImage* image ) +{ + if (image) Ref(*image); +} + +void wxImage::Create( int width, int height ) +{ + m_refData = new wxImageRefData(); + + M_IMGDATA->m_data = (unsigned char *) malloc( width*height*3 ); + if (M_IMGDATA->m_data) + { + for (int l = 0; l < width*height*3; l++) M_IMGDATA->m_data[l] = 0; + + M_IMGDATA->m_width = width; + M_IMGDATA->m_height = height; + M_IMGDATA->m_ok = TRUE; + } + else + { + UnRef(); + } +} + +void wxImage::Destroy() +{ + UnRef(); +} + +bool wxImage::Ok() const +{ + return (M_IMGDATA && M_IMGDATA->m_ok); +} + +char unsigned *wxImage::GetData() const +{ + if (!Ok()) return (char unsigned *)NULL; + + return M_IMGDATA->m_data; +} + +void wxImage::SetData( char unsigned *WXUNUSED(data) ) +{ +} + +void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b ) +{ + if (!Ok()) return; + + M_IMGDATA->m_maskRed = r; + M_IMGDATA->m_maskGreen = g; + M_IMGDATA->m_maskBlue = b; + M_IMGDATA->m_hasMask = TRUE; +} + +unsigned char wxImage::GetMaskRed() const +{ + if (!Ok()) return 0; + + return M_IMGDATA->m_maskRed; +} + +unsigned char wxImage::GetMaskGreen() const +{ + if (!Ok()) return 0; + + return M_IMGDATA->m_maskGreen; +} + +unsigned char wxImage::GetMaskBlue() const +{ + if (!Ok()) return 0; + + return M_IMGDATA->m_maskBlue; +} + +void wxImage::SetMask( bool mask ) +{ + if (!Ok()) return; + + M_IMGDATA->m_hasMask = mask; +} + +bool wxImage::HasMask() const +{ + if (!Ok()) return FALSE; + + return M_IMGDATA->m_hasMask; +} + +int wxImage::GetWidth() const +{ + return (M_IMGDATA ? M_IMGDATA->m_width : 0); +} + +int wxImage::GetHeight() const +{ + return (M_IMGDATA ? M_IMGDATA->m_height : 0); +} + +bool wxImage::LoadFile( const wxString& filename, long type ) +{ + UnRef(); + + m_refData = new wxImageRefData; + + wxImageHandler *handler = FindHandler(type); + + if (handler == NULL) + { + wxLogWarning( "No image handler for type %d defined.", type ); + + return FALSE; + } + + return handler->LoadFile( this, filename ); +} + +bool wxImage::SaveFile( const wxString& filename, int type ) +{ + wxImageHandler *handler = FindHandler(type); + + if (handler == NULL) + { + wxLogWarning( "No image handler for type %d defined.", type ); + + return FALSE; + } + + return handler->SaveFile( this, filename ); +} + +void wxImage::AddHandler( wxImageHandler *handler ) +{ + sm_handlers.Append( handler ); +} + +void wxImage::InsertHandler( wxImageHandler *handler ) +{ + sm_handlers.Insert( handler ); +} + +bool wxImage::RemoveHandler( const wxString& name ) +{ + wxImageHandler *handler = FindHandler(name); + if (handler) + { + sm_handlers.DeleteObject(handler); + return TRUE; + } + else + return FALSE; +} + +wxImageHandler *wxImage::FindHandler( const wxString& name ) +{ + wxNode *node = sm_handlers.First(); + while (node) + { + wxImageHandler *handler = (wxImageHandler*)node->Data(); + if (handler->GetName() == name) return handler; + node = node->Next(); + } + return (wxImageHandler *)NULL; +} + +wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType ) +{ + wxNode *node = sm_handlers.First(); + while (node) + { + wxImageHandler *handler = (wxImageHandler*)node->Data(); + if ( handler->GetExtension() == extension && + (bitmapType == -1 || handler->GetType() == bitmapType) ) + return handler; + node = node->Next(); + } + return (wxImageHandler*)NULL; +} + +wxImageHandler *wxImage::FindHandler( long bitmapType ) +{ + wxNode *node = sm_handlers.First(); + while (node) + { + wxImageHandler *handler = (wxImageHandler *)node->Data(); + if (handler->GetType() == bitmapType) return handler; + node = node->Next(); + } + return NULL; +} + +void wxImage::CleanUpHandlers() +{ + wxNode *node = sm_handlers.First(); + while (node) + { + wxImageHandler *handler = (wxImageHandler *)node->Data(); + wxNode *next = node->Next(); + delete handler; + delete node; + node = next; + } +} + +//----------------------------------------------------------------------------- +// wxImageHandler +//----------------------------------------------------------------------------- + +#if !USE_SHARED_LIBRARIES +IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject) +#endif + +bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), const wxString& WXUNUSED(name) ) +{ + return FALSE; +} + +bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), const wxString& WXUNUSED(name) ) +{ + return FALSE; +} + +//----------------------------------------------------------------------------- +// wxPNGHandler +//----------------------------------------------------------------------------- + +#if !USE_SHARED_LIBRARIES +IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler,wxImageHandler) +#endif + +bool wxPNGHandler::LoadFile( wxImage *image, const wxString& name ) +{ + FILE *f; + png_structp png_ptr; + png_infop info_ptr; + unsigned char *ptr, **lines, *ptr2; + int transp,bit_depth,color_type,interlace_type; + png_uint_32 width, height; + + image->Destroy(); + + transp = 0; + png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); + if (!png_ptr) return FALSE; + + info_ptr = png_create_info_struct( png_ptr ); + if (!info_ptr) + { + png_destroy_read_struct( &png_ptr, NULL, NULL ); + return FALSE; + } + + if (setjmp(png_ptr->jmpbuf)) + { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return FALSE; + } + + if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return FALSE; + } + + f = fopen( name, "rb" ); + png_init_io( png_ptr, f ); + + png_read_info( png_ptr, info_ptr ); + png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL ); + + if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand( png_ptr ); + + png_set_strip_16( png_ptr ); + png_set_packing( png_ptr ); + if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand( png_ptr ); + png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER ); + + image->Create( width, height ); + + if (!image->Ok()) + { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return FALSE; + } + + lines = (unsigned char **)malloc( height * sizeof(unsigned char *) ); + if (lines == NULL) + { + image->Destroy(); + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return FALSE; + } + + for (unsigned int i = 0; i < height; i++) + { + if ((lines[i] = (unsigned char *)malloc(width * (sizeof(unsigned char) * 4))) == NULL) + { + image->Destroy(); + for (unsigned int n = 0; n < i; n++) free( lines[n] ); + free( lines ); + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return FALSE; + } + } + + png_read_image( png_ptr, lines ); + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + ptr = image->GetData(); + if ((color_type == PNG_COLOR_TYPE_GRAY) || + (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + { + for (unsigned int y = 0; y < height; y++) + { + ptr2 = lines[y]; + for (unsigned int x = 0; x < width; x++) + { + unsigned char r = *ptr2++; + unsigned char a = *ptr2++; + if (a < 128) + { + *ptr++ = 255; + *ptr++ = 0; + *ptr++ = 255; + transp = 1; + } + else + { + *ptr++ = r; + *ptr++ = r; + *ptr++ = r; + } + } + } + } + else + { + for (unsigned int y = 0; y < height; y++) + { + ptr2 = lines[y]; + for (unsigned int x = 0; x < width; x++) + { + unsigned char r = *ptr2++; + unsigned char g = *ptr2++; + unsigned char b = *ptr2++; + unsigned char a = *ptr2++; + if (a < 128) + { + *ptr++ = 255; + *ptr++ = 0; + *ptr++ = 255; + transp = 1; + } + else + { + if ((r == 255) && (g == 0) && (b == 255)) r = 254; + *ptr++ = r; + *ptr++ = g; + *ptr++ = b; + } + } + } + } + for (unsigned int i = 0; i < height; i++) free( lines[i] ); + free( lines ); + if (transp) + image->SetMaskColour( 255, 0, 255 ); + else + image->SetMask( FALSE ); + + return TRUE; +} + + +bool wxPNGHandler::SaveFile( wxImage *image, const wxString& name ) +{ + FILE *f = fopen( name, "wb" ); + if (f) + { + png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + fclose( f ); + return FALSE; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(f); + png_destroy_write_struct( &png_ptr, (png_infopp)NULL ); + return FALSE; + } + + if (setjmp(png_ptr->jmpbuf)) + { + fclose( f ); + png_destroy_write_struct( &png_ptr, (png_infopp)NULL ); + return FALSE; + } + + png_init_io( png_ptr, f ); + png_set_IHDR( png_ptr, info_ptr, image->GetWidth(), image->GetHeight(), 8, + PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_color_8 sig_bit; + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = 8; + png_set_sBIT( png_ptr, info_ptr, &sig_bit ); + png_write_info( png_ptr, info_ptr ); + png_set_shift( png_ptr, &sig_bit ); + png_set_packing( png_ptr ); + + unsigned char *data = (unsigned char *)malloc( image->GetWidth()*4 ); + if (!data) + { + fclose( f ); + png_destroy_write_struct( &png_ptr, (png_infopp)NULL ); + return FALSE; + } + + for (int y = 0; y < image->GetHeight(); y++) + { + unsigned char *ptr = image->GetData() + (y * image->GetWidth() * 3); + for (int x = 0; x < image->GetWidth(); x++) + { + data[(x << 2) + 0] = *ptr++; + data[(x << 2) + 1] = *ptr++; + data[(x << 2) + 2] = *ptr++; + if ((data[(x << 2) + 0] == image->GetMaskRed()) && + (data[(x << 2) + 1] == image->GetMaskGreen()) && + (data[(x << 2) + 2] == image->GetMaskBlue())) + data[(x << 2) + 3] = 0; + else + data[(x << 2) + 3] = 255; + } + png_bytep row_ptr = data; + png_write_rows( png_ptr, &row_ptr, 1 ); + } + free(data); + png_write_end( png_ptr, info_ptr ); + png_destroy_write_struct( &png_ptr, (png_infopp)NULL ); + + fclose(f); + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// wxBMPHandler +//----------------------------------------------------------------------------- + +#if !USE_SHARED_LIBRARIES +IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler) +#endif + +bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name ) +{ + FILE *file; + unsigned char *data, *ptr; + int done, i, bpp, planes, comp, ncolors, line, column, + linesize, linepos, rshift = 0, gshift = 0, bshift = 0; + unsigned char byte; + short int word; + long int dbuf[4], dword, rmask = 0, gmask = 0, bmask = 0, offset, + size; + signed char bbuf[4]; + struct _cmap + { + unsigned char r, g, b; + } + *cmap = NULL; + +#define BI_RGB 0 +#define BI_RLE8 1 +#define BI_RLE4 2 +#define BI_BITFIELDS 3 + + image->Destroy(); + + file = fopen(name, "r"); + if (!file) + return NULL; + + done = 0; + /* + * Reading the bmp header + */ + + fread(&bbuf, 1, 2, file); + + fread(dbuf, 4, 4, file); + + size = dbuf[0]; + offset = dbuf[2]; + + fread(dbuf, 4, 2, file); + int width = (int)dbuf[0]; + int height = (int)dbuf[1]; + if (width > 32767) + { + fprintf(stderr, "IMLIB ERROR: Image width > 32767 pixels for file\n"); + fclose(file); + return FALSE; + } + if (height > 32767) + { + fprintf(stderr, "IMLIB ERROR: Image height > 32767 pixels for file\n"); + fclose(file); + return FALSE; + } + fread(&word, 2, 1, file); + planes = (int)word; + fread(&word, 2, 1, file); + bpp = (int)word; + if (bpp != 1 && bpp != 4 && bpp != 8 && bpp && 16 && bpp != 24 && bpp != 32) + { + fprintf(stderr, "IMLIB ERROR: unknown bitdepth in file\n"); + fclose(file); + return FALSE; + } + fread(dbuf, 4, 4, file); + comp = (int)dbuf[0]; + if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS) + { + fprintf(stderr, "IMLIB ERROR: unknown encoding in Windows BMP file\n"); + fclose(file); + return FALSE; + } + fread(dbuf, 4, 2, file); + ncolors = (int)dbuf[0]; + if (ncolors == 0) + ncolors = 1 << bpp; + /* some more sanity checks */ + if (((comp == BI_RLE4) && (bpp != 4)) || ((comp == BI_RLE8) && (bpp != 8)) || ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32))) + { + fprintf(stderr, "IMLIB ERROR: encoding of BMP doesn't match bitdepth\n"); + fclose(file); + return FALSE; + } + if (bpp < 16) + { + cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors); + + if (!cmap) + { + fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for color map in BMP file\n"); + fclose(file); + return FALSE; + } + } + else + cmap = NULL; + + image->Create( width, height ); + ptr = image->GetData(); + if (!ptr) + { + fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for RGB data in file\n"); + fclose(file); + if (cmap) + free(cmap); + return FALSE; + } + + /* + * Reading the palette, if it exists. + */ + if (bpp < 16 && ncolors != 0) + { + for (i = 0; i < ncolors; i++) + { + fread(bbuf, 1, 4, file); + cmap[i].b = bbuf[0]; + cmap[i].g = bbuf[1]; + cmap[i].r = bbuf[2]; + } + } + else if (bpp == 16 || bpp == 32) + { + if (comp == BI_BITFIELDS) + { + int bit = 0; + + fread(dbuf, 4, 3, file); + bmask = dbuf[0]; + gmask = dbuf[1]; + rmask = dbuf[2]; + /* find shift amount.. ugly, but i can't think of a better way */ + for (bit = 0; bit < bpp; bit++) + { + if (bmask & (1 << bit)) + bshift = bit; + if (gmask & (1 << bit)) + gshift = bit; + if (rmask & (1 << bit)) + rshift = bit; + } + } + else if (bpp == 16) + { + rmask = 0x7C00; + gmask = 0x03E0; + bmask = 0x001F; + rshift = 10; + gshift = 5; + bshift = 0; + } + else if (bpp == 32) + { + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; + rshift = 16; + gshift = 8; + bshift = 0; + } + } + + /* + * REading the image data + */ + fseek(file, offset, SEEK_SET); + data = ptr; + + /* set the whole image to the background color */ + if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8)) + { + for (i = 0; i < width * height; i++) + { + *ptr++ = cmap[0].r; + *ptr++ = cmap[0].g; + *ptr++ = cmap[0].b; + } + ptr = data; + } + line = 0; + column = 0; +#define poffset (line * width * 3 + column * 3) + + /* + * BMPs are stored upside down... hmmmmmmmmmm.... + */ + + linesize = ((width * bpp + 31) / 32) * 4; + for (line = (height - 1); line >= 0; line--) + { + linepos = 0; + for (column = 0; column < width;) + { + if (bpp < 16) + { + int index; + + linepos++; + byte = getc(file); + if (bpp == 1) + { + int bit = 0; + + for (bit = 0; bit < 8; bit++) + { + index = ((byte & (0x80 >> bit)) ? 1 : 0); + ptr[poffset] = cmap[index].r; + ptr[poffset + 1] = cmap[index].g; + ptr[poffset + 2] = cmap[index].b; + column++; + } + } + else if (bpp == 4) + { + if (comp == BI_RLE4) + { + fprintf(stderr, "can't deal with 4bit encoded yet.\n"); + image->Destroy(); + free(cmap); + return FALSE; + } + else + { + int nibble = 0; + + for (nibble = 0; nibble < 2; nibble++) + { + index = ((byte & (0xF0 >> nibble * 4)) >> (!nibble * 4)); + if (index >= 16) + index = 15; + ptr[poffset] = cmap[index].r; + ptr[poffset + 1] = cmap[index].g; + ptr[poffset + 2] = cmap[index].b; + column++; + } + } + } + else if (bpp == 8) + { + if (comp == BI_RLE8) + { + unsigned char first; + + first = byte; + byte = getc(file); + if (first == 0) + { + if (byte == 0) + { +/* column = width; */ + } + else if (byte == 1) + { + column = width; + line = -1; + } + else if (byte == 2) + { + byte = getc(file); + column += byte; + linepos = column * bpp / 8; + byte = getc(file); + line += byte; + } + else + { + int absolute = byte; + + for (i = 0; i < absolute; i++) + { + +linepos++; + byte = getc(file); + ptr[poffset] = cmap[byte].r; + ptr[poffset + 1] = cmap[byte].g; + ptr[poffset + 2] = cmap[byte].b; + column++; + } + if (absolute & 0x01) + byte = getc(file); + } + } + else + { + for (i = 0; i < first; i++) + { + ptr[poffset] = cmap[byte].r; + ptr[poffset + 1] = cmap[byte].g; + ptr[poffset + 2] = cmap[byte].b; + column++; + linepos++; + } + } + } + else + { + ptr[poffset] = cmap[byte].r; + ptr[poffset + 1] = cmap[byte].g; + ptr[poffset + 2] = cmap[byte].b; + column++; + linepos += size; + } + } + } + else if (bpp == 24) + { + linepos += fread(&bbuf, 1, 3, file); + ptr[poffset] = (unsigned char)bbuf[2]; + ptr[poffset + 1] = (unsigned char)bbuf[1]; + ptr[poffset + 2] = (unsigned char)bbuf[0]; + column++; + } + else if (bpp == 16) + { + unsigned char temp; + + linepos += fread(&word, 2, 1, file); + temp = (word & rmask) >> rshift; + ptr[poffset] = temp; + temp = (word & gmask) >> gshift; + ptr[poffset + 1] = temp; + temp = (word & bmask) >> gshift; + ptr[poffset + 2] = temp; + column++; + } + else + { + unsigned char temp; + + linepos += fread(&dword, 4, 1, file); + temp = (dword & rmask) >> rshift; + ptr[poffset] = temp; + temp = (dword & gmask) >> gshift; + ptr[poffset + 1] = temp; + temp = (dword & bmask) >> bshift; + ptr[poffset + 2] = temp; + column++; + } + } + while ((linepos < linesize) && (comp != 1) && (comp != 2)) + { + int temp = fread(&byte, 1, 1, file); + + linepos += temp; + if (!temp) + break; + } + } + if (cmap) free(cmap); + + image->SetMask( FALSE ); + + fclose(file); + return TRUE; +} + diff --git a/src/generic/imaglist.cpp b/src/generic/imaglist.cpp index 20a5101650..fcc9c4e173 100644 --- a/src/generic/imaglist.cpp +++ b/src/generic/imaglist.cpp @@ -2,9 +2,8 @@ // Name: imaglist.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -91,15 +90,6 @@ bool wxImageList::RemoveAll() bool wxImageList::GetSize( int index, int &width, int &height ) const { -#ifdef __WXGTK__ - - width = m_width; - height = m_height; - - return (m_images.Nth( index ) != NULL); - -#else - wxNode *node = m_images.Nth( index ); if (node) { @@ -114,8 +104,6 @@ bool wxImageList::GetSize( int index, int &width, int &height ) const height = 0; return FALSE; } - -#endif } bool wxImageList::Draw( int index, wxDC &dc, int x, int y, @@ -125,19 +113,6 @@ bool wxImageList::Draw( int index, wxDC &dc, int x, int y, if (!node) return FALSE; wxBitmap *bm = (wxBitmap*)node->Data(); -#ifdef __WXGTK__ - - // As X doesn't have a standard size for icons, we resize here. - // Otherwise we'd simply have to forbid different bitmap sizes. - - if ((m_width != bm->GetWidth()) || - (m_height != bm->GetHeight())) - { - bm->Resize( m_width, m_height ); - } - -#endif - wxIcon *icon = (wxIcon*)bm; dc.DrawIcon( *icon, x, y, (flags & wxIMAGELIST_DRAW_TRANSPARENT) > 0 ); diff --git a/src/gtk.inc b/src/gtk.inc index 063d5cca2f..507bb5b075 100644 --- a/src/gtk.inc +++ b/src/gtk.inc @@ -25,6 +25,7 @@ LIB_CPP_SRC=\ common/hash.cpp \ common/helpbase.cpp \ common/intl.cpp \ + common/image.cpp \ common/ipcbase.cpp \ common/layout.cpp \ common/list.cpp \ @@ -167,12 +168,3 @@ LIB_C_SRC=\ zlib/infcodes.c \ zlib/infutil.c \ zlib/inffast.c \ -\ - gdk_imlib/cache.c \ - gdk_imlib/colors.c \ - gdk_imlib/globals.c \ - gdk_imlib/load.c \ - gdk_imlib/misc.c \ - gdk_imlib/rend.c \ - gdk_imlib/save.c \ - gdk_imlib/utils.c diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp index fb0c54118a..d65cff17cf 100644 --- a/src/gtk/app.cpp +++ b/src/gtk/app.cpp @@ -2,9 +2,8 @@ // Name: app.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling, Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -24,10 +23,6 @@ #include "unistd.h" -#ifdef wxUSE_GDK_IMLIB -#include "../gdk_imlib/gdk_imlib.h" -#endif - //----------------------------------------------------------------------------- // global data //----------------------------------------------------------------------------- @@ -38,6 +33,74 @@ wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL; extern wxList wxPendingDelete; extern wxResourceCache *wxTheResourceCache; +unsigned char g_palette[64*3] = +{ + 0x0, 0x0, 0x0, + 0xff, 0xff, 0xff, + 0xff, 0x0, 0x0, + 0xff, 0xff, 0x0, + 0x0, 0xff, 0x0, + 0x0, 0x0, 0xff, + 0x0, 0xff, 0xff, + 0x99, 0x99, 0x99, + 0xff, 0x88, 0x0, + 0x88, 0x0, 0x0, + 0x0, 0x88, 0x88, + 0x88, 0x88, 0x0, + 0xff, 0xcc, 0x97, + 0xbb, 0xbb, 0xbb, + 0x9f, 0x6b, 0x42, + 0x55, 0x55, 0x55, + 0xdd, 0xdd, 0xdd, + 0x77, 0x77, 0x77, + 0x33, 0x33, 0x33, + 0xcc, 0x0, 0x0, + 0xff, 0x44, 0x0, + 0xff, 0xcc, 0x0, + 0xcc, 0xcc, 0x0, + 0x60, 0x60, 0x0, + 0x0, 0x43, 0x0, + 0x0, 0x7f, 0x0, + 0x0, 0xcc, 0x0, + 0x0, 0x44, 0x44, + 0x0, 0x0, 0x44, + 0x0, 0x0, 0x88, + 0xef, 0xb1, 0x7b, + 0xdf, 0x98, 0x5f, + 0xbf, 0x87, 0x56, + 0x7f, 0x57, 0x26, + 0x5f, 0x39, 0xc, + 0x3f, 0x1c, 0x0, + 0x21, 0x0, 0x0, + 0x0, 0x43, 0x87, + 0x2d, 0x70, 0xaf, + 0x5a, 0x9e, 0xd7, + 0x87, 0xcc, 0xff, + 0xff, 0xe0, 0xba, + 0x21, 0x43, 0xf, + 0x3d, 0x5d, 0x25, + 0x59, 0x78, 0x3a, + 0x75, 0x93, 0x4f, + 0x91, 0xae, 0x64, + 0xad, 0xc8, 0x7a, + 0xf0, 0xa8, 0xef, + 0xd0, 0x88, 0xd0, + 0xaf, 0x66, 0xaf, + 0x8e, 0x44, 0x8e, + 0x6d, 0x22, 0x6d, + 0x4b, 0x0, 0x4b, + 0xff, 0xc0, 0xbc, + 0xff, 0x93, 0x91, + 0xff, 0x66, 0x67, + 0xd8, 0xf2, 0xbf, + 0xff, 0xc9, 0x68, + 0xff, 0x96, 0x67, + 0xa5, 0x60, 0xff, + 0x51, 0xff, 0x99, + 0x3f, 0xa5, 0x63, + 0x98, 0x90, 0x67 +}; + //----------------------------------------------------------------------------- // local functions //----------------------------------------------------------------------------- @@ -355,15 +418,22 @@ int wxEntry( int argc, char *argv[] ) gtk_init( &argc, &argv ); -#ifdef wxUSE_GDK_IMLIB - - gdk_imlib_init(); - - gtk_widget_push_visual(gdk_imlib_get_visual()); + GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE ); - gtk_widget_push_colormap(gdk_imlib_get_colormap()); - -#endif + for (int i = 0; i < 64; i++) + { + GdkColor col; + col.red = g_palette[i*3 + 0] << 8; + col.green = g_palette[i*3 + 1] << 8; + col.blue = g_palette[i*3 + 2] << 8; + col.pixel = 0; + + gdk_color_alloc( cmap, &col ); + } + + gtk_widget_push_colormap( cmap ); + + gtk_widget_set_default_colormap( cmap ); wxApp::CommonInit(); diff --git a/src/gtk/bitmap.cpp b/src/gtk/bitmap.cpp index 07519ea19f..4706c2e7d7 100644 --- a/src/gtk/bitmap.cpp +++ b/src/gtk/bitmap.cpp @@ -2,9 +2,8 @@ // Name: bitmap.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -15,15 +14,7 @@ #include "wx/bitmap.h" #include "wx/icon.h" #include "gdk/gdkprivate.h" - -#ifdef wxUSE_GDK_IMLIB - -#include "../gdk_imlib/gdk_imlib.h" -#include "gdk/gdkx.h" // GDK_DISPLAY -#include -#include - -#endif +#include "gdk/gdkx.h" //----------------------------------------------------------------------------- // wxMask @@ -50,11 +41,7 @@ wxMask::wxMask( const wxBitmap& WXUNUSED(bitmap) ) wxMask::~wxMask(void) { -#ifdef wxUSE_GDK_IMLIB - // do not delete the mask, gdk_imlib does it for you -#else if (m_bitmap) gdk_bitmap_unref( m_bitmap ); -#endif } GdkBitmap *wxMask::GetBitmap(void) const @@ -66,7 +53,6 @@ GdkBitmap *wxMask::GetBitmap(void) const // wxBitmap //----------------------------------------------------------------------------- -// CMB 20/5/98: added m_bitmap for GdkBitmaps class wxBitmapRefData: public wxObjectRefData { public: @@ -80,9 +66,6 @@ class wxBitmapRefData: public wxObjectRefData int m_width; int m_height; int m_bpp; -#ifdef wxUSE_GDK_IMLIB - GdkImlibImage *m_image; -#endif wxPalette *m_palette; }; @@ -95,19 +78,11 @@ wxBitmapRefData::wxBitmapRefData(void) m_height = 0; m_bpp = 0; m_palette = (wxPalette *) NULL; -#ifdef wxUSE_GDK_IMLIB - m_image = (GdkImlibImage *) NULL; -#endif } wxBitmapRefData::~wxBitmapRefData(void) { -#ifdef wxUSE_GDK_IMLIB - if (m_pixmap) gdk_imlib_free_pixmap( m_pixmap ); - if (m_image) gdk_imlib_kill_image( m_image ); -#else if (m_pixmap) gdk_pixmap_unref( m_pixmap ); -#endif if (m_bitmap) gdk_bitmap_unref( m_bitmap ); if (m_mask) delete m_mask; if (m_palette) delete m_palette; @@ -141,8 +116,6 @@ wxBitmap::wxBitmap( char **bits ) { m_refData = new wxBitmapRefData(); -#ifndef wxUSE_GDK_IMLIB - GdkBitmap *mask = NULL; M_BMPDATA->m_pixmap = @@ -156,13 +129,6 @@ wxBitmap::wxBitmap( char **bits ) gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) ); -#else - - M_BMPDATA->m_image = gdk_imlib_create_image_from_xpm_data( bits ); - Render(); - -#endif - M_BMPDATA->m_bpp = 24; // ? if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this); @@ -189,7 +155,6 @@ wxBitmap::wxBitmap( const wxString &filename, int type ) if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this); } -// CMB 15/5/98: add constructor for xbm bitmaps wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth)) { m_refData = new wxBitmapRefData(); @@ -315,43 +280,7 @@ void wxBitmap::SetMask( wxMask *mask ) M_BMPDATA->m_mask = mask; } -void wxBitmap::Resize( int height, int width ) -{ - if (!Ok()) - { - wxFAIL_MSG( "invalid bitmap" ); - return; - } - -#ifdef wxUSE_GDK_IMLIB - - if (M_BMPDATA->m_bitmap) - { - wxFAIL_MSG( "wxBitmap::Resize not supported for mono-bitmaps" ); - return; - } - - if (!M_BMPDATA->m_image) RecreateImage(); - - if (M_BMPDATA->m_pixmap) gdk_imlib_free_pixmap( M_BMPDATA->m_pixmap ); - if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask; - - GdkImlibImage* image = gdk_imlib_clone_scaled_image( M_BMPDATA->m_image, height, width ); - gdk_imlib_destroy_image( M_BMPDATA->m_image ); - M_BMPDATA->m_image = image; - M_BMPDATA->m_height = height; - M_BMPDATA->m_width = width; - - Render(); - -#else - - wxFAIL_MSG( "wxBitmap::Resize not implemented without GdkImlib" ); - -#endif -} - -bool wxBitmap::SaveFile( const wxString &name, int WXUNUSED(type), +bool wxBitmap::SaveFile( const wxString &WXUNUSED(name), int WXUNUSED(type), wxPalette *WXUNUSED(palette) ) { if (!Ok()) @@ -360,55 +289,17 @@ bool wxBitmap::SaveFile( const wxString &name, int WXUNUSED(type), return FALSE; } -#ifdef wxUSE_GDK_IMLIB - - if (M_BMPDATA->m_bitmap) - { - wxFAIL_MSG( "wxBitmap::SaveFile not supported for mono-bitmaps" ); - return FALSE; - } - - if (!M_BMPDATA->m_image) RecreateImage(); - - return gdk_imlib_save_image( M_BMPDATA->m_image, WXSTRINGCAST name, (GdkImlibSaveInfo *) NULL ); - -#else - - wxFAIL_MSG( "wxBitmap::SaveFile not implemented without GdkImlib" ); - -#endif - return FALSE; } -bool wxBitmap::LoadFile( const wxString &name, int WXUNUSED(type) ) +bool wxBitmap::LoadFile( const wxString &WXUNUSED(name), int WXUNUSED(type) ) { -#ifdef wxUSE_GDK_IMLIB - - UnRef(); - m_refData = new wxBitmapRefData(); - - M_BMPDATA->m_image = gdk_imlib_load_image( WXSTRINGCAST name ); - - if (!M_BMPDATA->m_image) + if (!Ok()) { - UnRef(); + wxFAIL_MSG( "invalid bitmap" ); return FALSE; } - - Render(); - - gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) ); - M_BMPDATA->m_bpp = 24; // ? - - return TRUE; - -#else - - wxFAIL_MSG( "wxBitmap::LoadFile not implemented without GdkImlib" ); -#endif - return FALSE; } @@ -426,8 +317,6 @@ GdkPixmap *wxBitmap::GetPixmap(void) const return (GdkPixmap *) NULL; } -// if (!M_BMPDATA->m_image) RecreateImage(); - return M_BMPDATA->m_pixmap; } @@ -442,118 +331,200 @@ GdkBitmap *wxBitmap::GetBitmap(void) const return M_BMPDATA->m_bitmap; } -void wxBitmap::DestroyImage(void) +wxBitmap::wxBitmap( const wxImage &image ) { - if (!Ok()) - { - wxFAIL_MSG( "invalid bitmap" ); - return; - } + if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this); - if (M_BMPDATA->m_image) - { - gdk_imlib_destroy_image( M_BMPDATA->m_image ); - M_BMPDATA->m_image = (GdkImlibImage *) NULL; - } -} + if (!image.Ok()) return; -void wxBitmap::RecreateImage(void) -{ - if (!Ok()) - { - wxFAIL_MSG( "invalid bitmap" ); - return; - } - -#ifdef wxUSE_GDK_IMLIB + m_refData = new wxBitmapRefData(); - DestroyImage(); + M_BMPDATA->m_height = image.GetHeight(); + M_BMPDATA->m_width = image.GetWidth(); + int width = image.GetWidth(); + int height = image.GetHeight(); + + // Create picture - wxCHECK_RET( M_BMPDATA->m_pixmap != NULL, "invalid bitmap" ); + GdkImage *data_image = + gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height ); - long size = (long)(M_BMPDATA->m_width)*(long)(M_BMPDATA->m_height)*(long)3; - unsigned char *data = new unsigned char[size]; - for (long i = 0; i < size; i++) data[i] = 100; + M_BMPDATA->m_pixmap = + gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ); + + // Create mask - GdkImage *image = gdk_image_get( M_BMPDATA->m_pixmap, 0, 0, M_BMPDATA->m_width, M_BMPDATA->m_height ); + GdkImage *mask_image = (GdkImage*) NULL; - long pos = 0; - for (int j = 0; j < M_BMPDATA->m_height; j++) + if (image.HasMask()) { - for (int i = 0; i < M_BMPDATA->m_width; i++) - { - XColor xcol; - xcol.pixel = gdk_image_get_pixel( image, i, j ); - Colormap cm = ((GdkColormapPrivate*)gdk_imlib_get_colormap())->xcolormap; - XQueryColor( gdk_display, cm, &xcol ); - - data[pos] = xcol.red; - data[pos+1] = xcol.green; - data[pos+2] = xcol.blue; - pos += 3; - } + unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height ); + + mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height ); + + M_BMPDATA->m_mask = new wxMask(); + M_BMPDATA->m_mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 ); } - wxCHECK_RET( M_BMPDATA->m_pixmap != NULL, "invalid bitmap" ); + // Retrieve depth + + M_BMPDATA->m_bpp = data_image->depth; + + int render_depth = 8; + if (M_BMPDATA->m_bpp > 8) render_depth = M_BMPDATA->m_bpp; + + // Render + + int r_mask = image.GetMaskRed(); + int g_mask = image.GetMaskGreen(); + int b_mask = image.GetMaskBlue(); + + unsigned char* data = image.GetData(); + + int index = 0; + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + { + int r = data[index]; + index++; + int g = data[index]; + index++; + int b = data[index]; + index++; + + if (image.HasMask()) + { + if ((r == r_mask) && (b = b_mask) && (g = g_mask)) + gdk_image_put_pixel( mask_image, x, y, 0 ); + else + gdk_image_put_pixel( mask_image, x, y, 1 ); + } + + switch (render_depth) + { + case 8: + { + GdkColormap *cmap = gtk_widget_get_default_colormap(); + GdkColor *colors = cmap->colors; + int max = 3 * (65536); + int index = -1; + + for (int i = 0; i < cmap->size; i++) + { + int rdiff = (r << 8) - colors[i].red; + int gdiff = (g << 8) - colors[i].green; + int bdiff = (b << 8) - colors[i].blue; + int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff); + if (sum < max) { index = i; max = sum; } + } + + gdk_image_put_pixel( data_image, x, y, index ); + + break; + } + case 15: + { + guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); + gdk_image_put_pixel( data_image, x, y, pixel ); + break; + } + case 16: + { + guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); + gdk_image_put_pixel( data_image, x, y, pixel ); + break; + } + case 24: + { + break; + } + case 32: + { + break; + } + default: break; + } + } + + // Blit picture - M_BMPDATA->m_image = gdk_imlib_create_image_from_data( - data, (unsigned char*)NULL, M_BMPDATA->m_width, M_BMPDATA->m_height ); + GdkGC *data_gc = gdk_gc_new( M_BMPDATA->m_pixmap ); - delete[] data; + gdk_draw_image( M_BMPDATA->m_pixmap, data_gc, data_image, 0, 0, 0, 0, width, height ); - gdk_image_destroy( image ); + gdk_image_destroy( data_image ); + gdk_gc_unref( data_gc ); - Render(); + // Blit mask -#else + if (image.HasMask()) + { + GdkGC *mask_gc = gdk_gc_new( M_BMPDATA->m_mask->m_bitmap ); - wxFAIL_MSG( "wxBitmap::RecreateImage not implemented without GdkImlib" ); + gdk_draw_image( M_BMPDATA->m_mask->m_bitmap, mask_gc, mask_image, 0, 0, 0, 0, width, height ); -#endif + gdk_image_destroy( mask_image ); + gdk_gc_unref( mask_gc ); + } + } -void wxBitmap::Render(void) +wxImage wxBitmap::ConvertToImage() const { + wxImage image; + if (!Ok()) { wxFAIL_MSG( "invalid bitmap" ); - return; + return image; } -#ifdef wxUSE_GDK_IMLIB - - if (!M_BMPDATA->m_image) RecreateImage(); + GdkImage *gdk_image = gdk_image_get( M_BMPDATA->m_pixmap, 0, 0, M_BMPDATA->m_width, M_BMPDATA->m_height ); - if (M_BMPDATA->m_pixmap) - { - gdk_imlib_free_pixmap( M_BMPDATA->m_pixmap ); - M_BMPDATA->m_pixmap = (GdkPixmap*) NULL; - } - if (M_BMPDATA->m_mask) - { - delete M_BMPDATA->m_mask; - M_BMPDATA->m_mask = (wxMask*) NULL; - } + if (!gdk_image) return image; - gdk_imlib_render( M_BMPDATA->m_image, M_BMPDATA->m_image->rgb_width, M_BMPDATA->m_image->rgb_height ); - M_BMPDATA->m_width = M_BMPDATA->m_image->rgb_width; - M_BMPDATA->m_height = M_BMPDATA->m_image->rgb_height; - M_BMPDATA->m_pixmap = gdk_imlib_move_image( M_BMPDATA->m_image ); + image.Create( M_BMPDATA->m_width, M_BMPDATA->m_height ); + char unsigned *data = image.GetData(); - wxCHECK_RET( M_BMPDATA->m_pixmap != NULL, "pixmap rendering failed" ) + int bpp = gdk_image->bpp; + GdkColormap *cmap = gtk_widget_get_default_colormap(); - GdkBitmap *mask = gdk_imlib_move_mask( M_BMPDATA->m_image ); - if (mask) + long pos = 0; + for (int j = 0; j < M_BMPDATA->m_height; j++) { - M_BMPDATA->m_mask = new wxMask(); - M_BMPDATA->m_mask->m_bitmap = mask; + for (int i = 0; i < M_BMPDATA->m_width; i++) + { + int pixel = gdk_image_get_pixel( gdk_image, i, j ); + if (bpp <= 8) + { + data[pos] = cmap->colors[pixel].red >> 8; + data[pos+1] = cmap->colors[pixel].green >> 8; + data[pos+2] = cmap->colors[pixel].blue >> 8; + } else if (bpp == 15) + { + data[pos] = (pixel >> 7) & 0xf8; + data[pos+1] = (pixel >> 3) & 0xf8; + data[pos+2] = (pixel << 3) & 0xf8; + } else if (bpp == 16) + { + data[pos] = (pixel >> 8) & 0xf8; + data[pos+1] = (pixel >> 3) & 0xfc; + data[pos+2] = (pixel << 3) & 0xf8; + } else + { + data[pos] = (pixel >> 16) & 0xff; + data[pos+1] = (pixel >> 8) & 0xff; + data[pos+2] = pixel & 0xff; + } + + pos += 3; + } } -#else + gdk_image_destroy( gdk_image ); - wxFAIL_MSG( "wxBitmap::Render not implemented without GdkImlib" ); - -#endif + return image; } + diff --git a/src/gtk/bmpbuttn.cpp b/src/gtk/bmpbuttn.cpp index 25968dbcd8..df7d7f6a1a 100644 --- a/src/gtk/bmpbuttn.cpp +++ b/src/gtk/bmpbuttn.cpp @@ -2,9 +2,8 @@ // Name: bmpbuttn.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/brush.cpp b/src/gtk/brush.cpp index ae90ec472d..29131bbede 100644 --- a/src/gtk/brush.cpp +++ b/src/gtk/brush.cpp @@ -2,9 +2,8 @@ // Name: brush.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/button.cpp b/src/gtk/button.cpp index 034e229f18..b0278860ac 100644 --- a/src/gtk/button.cpp +++ b/src/gtk/button.cpp @@ -2,9 +2,8 @@ // Name: button.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/checkbox.cpp b/src/gtk/checkbox.cpp index c4aac9364a..385f9bc7c3 100644 --- a/src/gtk/checkbox.cpp +++ b/src/gtk/checkbox.cpp @@ -2,9 +2,8 @@ // Name: checkbox.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/choice.cpp b/src/gtk/choice.cpp index edcf64f3e9..f6e3925ea4 100644 --- a/src/gtk/choice.cpp +++ b/src/gtk/choice.cpp @@ -2,9 +2,8 @@ // Name: choice.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/colour.cpp b/src/gtk/colour.cpp index b7c2dc1176..7e57df104f 100644 --- a/src/gtk/colour.cpp +++ b/src/gtk/colour.cpp @@ -15,9 +15,7 @@ #include "wx/gdicmn.h" -#ifdef wxUSE_GDK_IMLIB -#include "../gdk_imlib/gdk_imlib.h" -#endif +#include "gdk/gdkprivate.h" //----------------------------------------------------------------------------- // wxColour @@ -186,19 +184,30 @@ void wxColour::CalcPixel( GdkColormap *cmap ) if ((M_COLDATA->m_hasPixel) && (M_COLDATA->m_colormap == cmap)) return; M_COLDATA->FreeColour(); -#ifdef wxUSE_GDK_IMLIB - - int r = M_COLDATA->m_color.red >> SHIFT; - int g = M_COLDATA->m_color.green >> SHIFT; - int b = M_COLDATA->m_color.blue >> SHIFT; - M_COLDATA->m_hasPixel = TRUE; - M_COLDATA->m_color.pixel = gdk_imlib_best_color_match( &r, &g, &b ); - -#else + GdkColormapPrivate *private_colormap = (GdkColormapPrivate*) cmap; + if ((private_colormap->visual->type == GDK_VISUAL_GRAYSCALE) || + (private_colormap->visual->type == GDK_VISUAL_PSEUDO_COLOR)) + { + GdkColor *colors = cmap->colors; + int max = 3 * (65536); + int index = -1; - M_COLDATA->m_hasPixel = gdk_color_alloc( cmap, &M_COLDATA->m_color ); - -#endif + for (int i = 0; i < cmap->size; i++) + { + int rdiff = (M_COLDATA->m_color.red - colors[i].red); + int gdiff = (M_COLDATA->m_color.green - colors[i].green); + int bdiff = (M_COLDATA->m_color.blue - colors[i].blue); + int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff); + if (sum < max) { index = i; max = sum; } + } + + M_COLDATA->m_hasPixel = TRUE; + M_COLDATA->m_color.pixel = index; + } + else + { + M_COLDATA->m_hasPixel = gdk_color_alloc( cmap, &M_COLDATA->m_color ); + } M_COLDATA->m_colormap = cmap; } diff --git a/src/gtk/combobox.cpp b/src/gtk/combobox.cpp index efe78a6f3f..59f2f9821e 100644 --- a/src/gtk/combobox.cpp +++ b/src/gtk/combobox.cpp @@ -2,9 +2,8 @@ // Name: combobox.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/control.cpp b/src/gtk/control.cpp index 61bab59ecf..658ebcd8c9 100644 --- a/src/gtk/control.cpp +++ b/src/gtk/control.cpp @@ -2,9 +2,8 @@ // Name: control.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling, Julian Smart and Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/cursor.cpp b/src/gtk/cursor.cpp index 7195cfa0c6..20a8d3c19e 100644 --- a/src/gtk/cursor.cpp +++ b/src/gtk/cursor.cpp @@ -2,9 +2,8 @@ // Name: cursor.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/data.cpp b/src/gtk/data.cpp index 96bce38d00..815bdca347 100644 --- a/src/gtk/data.cpp +++ b/src/gtk/data.cpp @@ -2,8 +2,7 @@ // Name: data.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: +// Id: $id$ // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/dc.cpp b/src/gtk/dc.cpp index 13ffab2a44..3678494de4 100644 --- a/src/gtk/dc.cpp +++ b/src/gtk/dc.cpp @@ -2,7 +2,6 @@ // Name: dc.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem // Licence: wxWindows licence diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index 17cd007433..a724a4d51c 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -2,9 +2,8 @@ // Name: dcclient.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -138,8 +137,6 @@ void wxPaintDC::DrawLine( long x1, long y1, long x2, long y2 ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() != wxTRANSPARENT) { gdk_draw_line( m_window, m_penGC, @@ -151,8 +148,6 @@ void wxPaintDC::CrossHair( long x, long y ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() != wxTRANSPARENT) { int w = 0; @@ -171,8 +166,6 @@ void wxPaintDC::DrawArc( long x1, long y1, long x2, long y2, double xc, double y { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - long xx1 = XLOG2DEV(x1); long yy1 = YLOG2DEV(y1); long xx2 = XLOG2DEV(x2); @@ -221,8 +214,6 @@ void wxPaintDC::DrawEllipticArc( long x, long y, long width, long height, double { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - long xx = XLOG2DEV(x); long yy = YLOG2DEV(y); long ww = m_signX * XLOG2DEVREL(width); @@ -245,8 +236,6 @@ void wxPaintDC::DrawPoint( long x, long y ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() != wxTRANSPARENT) gdk_draw_point( m_window, m_penGC, XLOG2DEV(x), YLOG2DEV(y) ); } @@ -255,8 +244,6 @@ void wxPaintDC::DrawLines( int n, wxPoint points[], long xoffset, long yoffset ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() == wxTRANSPARENT) return; for (int i = 0; i < n-1; i++) @@ -273,8 +260,6 @@ void wxPaintDC::DrawLines( wxList *points, long xoffset, long yoffset ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() == wxTRANSPARENT) return; wxNode *node = points->First(); @@ -295,8 +280,6 @@ void wxPaintDC::DrawPolygon( int n, wxPoint points[], long xoffset, long yoffset { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (!n) return; // Nothing to draw GdkPoint *gdkpoints = new GdkPoint[n+1]; int i; @@ -322,8 +305,6 @@ void wxPaintDC::DrawPolygon( wxList *lines, long xoffset, long yoffset, int WXUN { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - int n = lines->Number(); GdkPoint *gdkpoints = new GdkPoint[n]; wxNode *node = lines->First(); @@ -356,8 +337,6 @@ void wxPaintDC::DrawRectangle( long x, long y, long width, long height ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - long xx = XLOG2DEV(x); long yy = YLOG2DEV(y); long ww = m_signX * XLOG2DEVREL(width); @@ -381,8 +360,6 @@ void wxPaintDC::DrawRoundedRectangle( long x, long y, long width, long height, d { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (radius < 0.0) radius = - radius * ((width < height) ? width : height); long xx = XLOG2DEV(x); @@ -448,8 +425,6 @@ void wxPaintDC::DrawEllipse( long x, long y, long width, long height ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - long xx = XLOG2DEV(x); long yy = YLOG2DEV(y); long ww = m_signX * XLOG2DEVREL(width); @@ -477,8 +452,6 @@ void wxPaintDC::DrawIcon( const wxIcon &icon, long x, long y, bool useMask ) if (!icon.Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - int xx = XLOG2DEV(x); int yy = YLOG2DEV(y); @@ -506,8 +479,6 @@ bool wxPaintDC::Blit( long xdest, long ydest, long width, long height, { if (!Ok()) return FALSE; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_isMemDC) { wxMemoryDC* srcDC = (wxMemoryDC*)source; @@ -547,8 +518,6 @@ void wxPaintDC::DrawText( const wxString &text, long x, long y, bool WXUNUSED(us { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - GdkFont *font = m_font.GetInternalFont( m_scaleY ); x = XLOG2DEV(x); @@ -618,8 +587,6 @@ void wxPaintDC::Clear(void) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (!m_isMemDC) { gdk_window_clear( m_window ); diff --git a/src/gtk/dcmemory.cpp b/src/gtk/dcmemory.cpp index aa8ab7a269..f346200a81 100644 --- a/src/gtk/dcmemory.cpp +++ b/src/gtk/dcmemory.cpp @@ -2,9 +2,8 @@ // Name: dcmemory.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -14,10 +13,6 @@ #include "wx/dcmemory.h" -#ifdef wxUSE_GDK_IMLIB -#include "../gdk_imlib/gdk_imlib.h" -#endif - //----------------------------------------------------------------------------- // wxMemoryDC //----------------------------------------------------------------------------- @@ -28,22 +23,14 @@ wxMemoryDC::wxMemoryDC(void) { m_ok = FALSE; -#ifdef wxUSE_GDK_IMLIB - m_cmap = gdk_imlib_get_colormap(); -#else - m_cmap = gdk_colormap_get_system(); -#endif + m_cmap = gtk_widget_get_default_colormap(); } wxMemoryDC::wxMemoryDC( wxDC *WXUNUSED(dc) ) { m_ok = FALSE; -#ifdef wxUSE_GDK_IMLIB - m_cmap = gdk_imlib_get_colormap(); -#else - m_cmap = gdk_colormap_get_system(); -#endif + m_cmap = gtk_widget_get_default_colormap(); } wxMemoryDC::~wxMemoryDC(void) diff --git a/src/gtk/dcscreen.cpp b/src/gtk/dcscreen.cpp index c3a9303751..cd47777fdb 100644 --- a/src/gtk/dcscreen.cpp +++ b/src/gtk/dcscreen.cpp @@ -2,9 +2,8 @@ // Name: dcscreen.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/dialog.cpp b/src/gtk/dialog.cpp index 73ae00a02b..9bbc5f9a28 100644 --- a/src/gtk/dialog.cpp +++ b/src/gtk/dialog.cpp @@ -2,9 +2,8 @@ // Name: dialog.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/dnd.cpp b/src/gtk/dnd.cpp index 458eb72641..4090bb15ec 100644 --- a/src/gtk/dnd.cpp +++ b/src/gtk/dnd.cpp @@ -2,8 +2,9 @@ // Name: dnd.cpp // Purpose: wxDropTarget class // Author: Robert Roebling -// Copyright: Robert Roebling -// Licence: wxWindows license +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ diff --git a/src/gtk/filedlg.cpp b/src/gtk/filedlg.cpp index 021946bb57..dae464b19f 100644 --- a/src/gtk/filedlg.cpp +++ b/src/gtk/filedlg.cpp @@ -2,9 +2,8 @@ // Name: filedlg.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/font.cpp b/src/gtk/font.cpp index ef95c79be8..119b9cc83c 100644 --- a/src/gtk/font.cpp +++ b/src/gtk/font.cpp @@ -2,8 +2,7 @@ // Name: font.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: +// Id: $id$ // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/frame.cpp b/src/gtk/frame.cpp index bead5e36e2..fbb256de87 100644 --- a/src/gtk/frame.cpp +++ b/src/gtk/frame.cpp @@ -2,9 +2,8 @@ // Name: frame.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/gauge.cpp b/src/gtk/gauge.cpp index 8499339d67..30688eda35 100644 --- a/src/gtk/gauge.cpp +++ b/src/gtk/gauge.cpp @@ -2,9 +2,8 @@ // Name: gauge.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/notebook.cpp b/src/gtk/notebook.cpp index 0a3b30089d..f006c328a0 100644 --- a/src/gtk/notebook.cpp +++ b/src/gtk/notebook.cpp @@ -2,9 +2,8 @@ // Name: notebook.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling, Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/timer.cpp b/src/gtk/timer.cpp index 4e36a67f14..89ecf05f6d 100644 --- a/src/gtk/timer.cpp +++ b/src/gtk/timer.cpp @@ -2,9 +2,8 @@ // Name: timer.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk/utilsgtk.cpp b/src/gtk/utilsgtk.cpp index 3de7efc8bc..086ef60b6b 100644 --- a/src/gtk/utilsgtk.cpp +++ b/src/gtk/utilsgtk.cpp @@ -2,7 +2,6 @@ // Name: utils.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // Id: $Id$ // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem // Licence: wxWindows licence diff --git a/src/gtk/win_gtk.c b/src/gtk/win_gtk.c index 3a999cdeff..c4e8c42101 100644 --- a/src/gtk/win_gtk.c +++ b/src/gtk/win_gtk.c @@ -1,10 +1,9 @@ /* /////////////////////////////////////////////////////////////////////////// // Name: wx_gtk.h -// Purpose: +// Purpose: native GTK+ widget for wxWindows // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////// */ diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 1e6c3b6b92..eb9b9dcb84 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -2,9 +2,8 @@ // Name: window.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling, Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/app.cpp b/src/gtk1/app.cpp index fb0c54118a..d65cff17cf 100644 --- a/src/gtk1/app.cpp +++ b/src/gtk1/app.cpp @@ -2,9 +2,8 @@ // Name: app.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling, Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -24,10 +23,6 @@ #include "unistd.h" -#ifdef wxUSE_GDK_IMLIB -#include "../gdk_imlib/gdk_imlib.h" -#endif - //----------------------------------------------------------------------------- // global data //----------------------------------------------------------------------------- @@ -38,6 +33,74 @@ wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL; extern wxList wxPendingDelete; extern wxResourceCache *wxTheResourceCache; +unsigned char g_palette[64*3] = +{ + 0x0, 0x0, 0x0, + 0xff, 0xff, 0xff, + 0xff, 0x0, 0x0, + 0xff, 0xff, 0x0, + 0x0, 0xff, 0x0, + 0x0, 0x0, 0xff, + 0x0, 0xff, 0xff, + 0x99, 0x99, 0x99, + 0xff, 0x88, 0x0, + 0x88, 0x0, 0x0, + 0x0, 0x88, 0x88, + 0x88, 0x88, 0x0, + 0xff, 0xcc, 0x97, + 0xbb, 0xbb, 0xbb, + 0x9f, 0x6b, 0x42, + 0x55, 0x55, 0x55, + 0xdd, 0xdd, 0xdd, + 0x77, 0x77, 0x77, + 0x33, 0x33, 0x33, + 0xcc, 0x0, 0x0, + 0xff, 0x44, 0x0, + 0xff, 0xcc, 0x0, + 0xcc, 0xcc, 0x0, + 0x60, 0x60, 0x0, + 0x0, 0x43, 0x0, + 0x0, 0x7f, 0x0, + 0x0, 0xcc, 0x0, + 0x0, 0x44, 0x44, + 0x0, 0x0, 0x44, + 0x0, 0x0, 0x88, + 0xef, 0xb1, 0x7b, + 0xdf, 0x98, 0x5f, + 0xbf, 0x87, 0x56, + 0x7f, 0x57, 0x26, + 0x5f, 0x39, 0xc, + 0x3f, 0x1c, 0x0, + 0x21, 0x0, 0x0, + 0x0, 0x43, 0x87, + 0x2d, 0x70, 0xaf, + 0x5a, 0x9e, 0xd7, + 0x87, 0xcc, 0xff, + 0xff, 0xe0, 0xba, + 0x21, 0x43, 0xf, + 0x3d, 0x5d, 0x25, + 0x59, 0x78, 0x3a, + 0x75, 0x93, 0x4f, + 0x91, 0xae, 0x64, + 0xad, 0xc8, 0x7a, + 0xf0, 0xa8, 0xef, + 0xd0, 0x88, 0xd0, + 0xaf, 0x66, 0xaf, + 0x8e, 0x44, 0x8e, + 0x6d, 0x22, 0x6d, + 0x4b, 0x0, 0x4b, + 0xff, 0xc0, 0xbc, + 0xff, 0x93, 0x91, + 0xff, 0x66, 0x67, + 0xd8, 0xf2, 0xbf, + 0xff, 0xc9, 0x68, + 0xff, 0x96, 0x67, + 0xa5, 0x60, 0xff, + 0x51, 0xff, 0x99, + 0x3f, 0xa5, 0x63, + 0x98, 0x90, 0x67 +}; + //----------------------------------------------------------------------------- // local functions //----------------------------------------------------------------------------- @@ -355,15 +418,22 @@ int wxEntry( int argc, char *argv[] ) gtk_init( &argc, &argv ); -#ifdef wxUSE_GDK_IMLIB - - gdk_imlib_init(); - - gtk_widget_push_visual(gdk_imlib_get_visual()); + GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE ); - gtk_widget_push_colormap(gdk_imlib_get_colormap()); - -#endif + for (int i = 0; i < 64; i++) + { + GdkColor col; + col.red = g_palette[i*3 + 0] << 8; + col.green = g_palette[i*3 + 1] << 8; + col.blue = g_palette[i*3 + 2] << 8; + col.pixel = 0; + + gdk_color_alloc( cmap, &col ); + } + + gtk_widget_push_colormap( cmap ); + + gtk_widget_set_default_colormap( cmap ); wxApp::CommonInit(); diff --git a/src/gtk1/bitmap.cpp b/src/gtk1/bitmap.cpp index 07519ea19f..4706c2e7d7 100644 --- a/src/gtk1/bitmap.cpp +++ b/src/gtk1/bitmap.cpp @@ -2,9 +2,8 @@ // Name: bitmap.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -15,15 +14,7 @@ #include "wx/bitmap.h" #include "wx/icon.h" #include "gdk/gdkprivate.h" - -#ifdef wxUSE_GDK_IMLIB - -#include "../gdk_imlib/gdk_imlib.h" -#include "gdk/gdkx.h" // GDK_DISPLAY -#include -#include - -#endif +#include "gdk/gdkx.h" //----------------------------------------------------------------------------- // wxMask @@ -50,11 +41,7 @@ wxMask::wxMask( const wxBitmap& WXUNUSED(bitmap) ) wxMask::~wxMask(void) { -#ifdef wxUSE_GDK_IMLIB - // do not delete the mask, gdk_imlib does it for you -#else if (m_bitmap) gdk_bitmap_unref( m_bitmap ); -#endif } GdkBitmap *wxMask::GetBitmap(void) const @@ -66,7 +53,6 @@ GdkBitmap *wxMask::GetBitmap(void) const // wxBitmap //----------------------------------------------------------------------------- -// CMB 20/5/98: added m_bitmap for GdkBitmaps class wxBitmapRefData: public wxObjectRefData { public: @@ -80,9 +66,6 @@ class wxBitmapRefData: public wxObjectRefData int m_width; int m_height; int m_bpp; -#ifdef wxUSE_GDK_IMLIB - GdkImlibImage *m_image; -#endif wxPalette *m_palette; }; @@ -95,19 +78,11 @@ wxBitmapRefData::wxBitmapRefData(void) m_height = 0; m_bpp = 0; m_palette = (wxPalette *) NULL; -#ifdef wxUSE_GDK_IMLIB - m_image = (GdkImlibImage *) NULL; -#endif } wxBitmapRefData::~wxBitmapRefData(void) { -#ifdef wxUSE_GDK_IMLIB - if (m_pixmap) gdk_imlib_free_pixmap( m_pixmap ); - if (m_image) gdk_imlib_kill_image( m_image ); -#else if (m_pixmap) gdk_pixmap_unref( m_pixmap ); -#endif if (m_bitmap) gdk_bitmap_unref( m_bitmap ); if (m_mask) delete m_mask; if (m_palette) delete m_palette; @@ -141,8 +116,6 @@ wxBitmap::wxBitmap( char **bits ) { m_refData = new wxBitmapRefData(); -#ifndef wxUSE_GDK_IMLIB - GdkBitmap *mask = NULL; M_BMPDATA->m_pixmap = @@ -156,13 +129,6 @@ wxBitmap::wxBitmap( char **bits ) gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) ); -#else - - M_BMPDATA->m_image = gdk_imlib_create_image_from_xpm_data( bits ); - Render(); - -#endif - M_BMPDATA->m_bpp = 24; // ? if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this); @@ -189,7 +155,6 @@ wxBitmap::wxBitmap( const wxString &filename, int type ) if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this); } -// CMB 15/5/98: add constructor for xbm bitmaps wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth)) { m_refData = new wxBitmapRefData(); @@ -315,43 +280,7 @@ void wxBitmap::SetMask( wxMask *mask ) M_BMPDATA->m_mask = mask; } -void wxBitmap::Resize( int height, int width ) -{ - if (!Ok()) - { - wxFAIL_MSG( "invalid bitmap" ); - return; - } - -#ifdef wxUSE_GDK_IMLIB - - if (M_BMPDATA->m_bitmap) - { - wxFAIL_MSG( "wxBitmap::Resize not supported for mono-bitmaps" ); - return; - } - - if (!M_BMPDATA->m_image) RecreateImage(); - - if (M_BMPDATA->m_pixmap) gdk_imlib_free_pixmap( M_BMPDATA->m_pixmap ); - if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask; - - GdkImlibImage* image = gdk_imlib_clone_scaled_image( M_BMPDATA->m_image, height, width ); - gdk_imlib_destroy_image( M_BMPDATA->m_image ); - M_BMPDATA->m_image = image; - M_BMPDATA->m_height = height; - M_BMPDATA->m_width = width; - - Render(); - -#else - - wxFAIL_MSG( "wxBitmap::Resize not implemented without GdkImlib" ); - -#endif -} - -bool wxBitmap::SaveFile( const wxString &name, int WXUNUSED(type), +bool wxBitmap::SaveFile( const wxString &WXUNUSED(name), int WXUNUSED(type), wxPalette *WXUNUSED(palette) ) { if (!Ok()) @@ -360,55 +289,17 @@ bool wxBitmap::SaveFile( const wxString &name, int WXUNUSED(type), return FALSE; } -#ifdef wxUSE_GDK_IMLIB - - if (M_BMPDATA->m_bitmap) - { - wxFAIL_MSG( "wxBitmap::SaveFile not supported for mono-bitmaps" ); - return FALSE; - } - - if (!M_BMPDATA->m_image) RecreateImage(); - - return gdk_imlib_save_image( M_BMPDATA->m_image, WXSTRINGCAST name, (GdkImlibSaveInfo *) NULL ); - -#else - - wxFAIL_MSG( "wxBitmap::SaveFile not implemented without GdkImlib" ); - -#endif - return FALSE; } -bool wxBitmap::LoadFile( const wxString &name, int WXUNUSED(type) ) +bool wxBitmap::LoadFile( const wxString &WXUNUSED(name), int WXUNUSED(type) ) { -#ifdef wxUSE_GDK_IMLIB - - UnRef(); - m_refData = new wxBitmapRefData(); - - M_BMPDATA->m_image = gdk_imlib_load_image( WXSTRINGCAST name ); - - if (!M_BMPDATA->m_image) + if (!Ok()) { - UnRef(); + wxFAIL_MSG( "invalid bitmap" ); return FALSE; } - - Render(); - - gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) ); - M_BMPDATA->m_bpp = 24; // ? - - return TRUE; - -#else - - wxFAIL_MSG( "wxBitmap::LoadFile not implemented without GdkImlib" ); -#endif - return FALSE; } @@ -426,8 +317,6 @@ GdkPixmap *wxBitmap::GetPixmap(void) const return (GdkPixmap *) NULL; } -// if (!M_BMPDATA->m_image) RecreateImage(); - return M_BMPDATA->m_pixmap; } @@ -442,118 +331,200 @@ GdkBitmap *wxBitmap::GetBitmap(void) const return M_BMPDATA->m_bitmap; } -void wxBitmap::DestroyImage(void) +wxBitmap::wxBitmap( const wxImage &image ) { - if (!Ok()) - { - wxFAIL_MSG( "invalid bitmap" ); - return; - } + if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this); - if (M_BMPDATA->m_image) - { - gdk_imlib_destroy_image( M_BMPDATA->m_image ); - M_BMPDATA->m_image = (GdkImlibImage *) NULL; - } -} + if (!image.Ok()) return; -void wxBitmap::RecreateImage(void) -{ - if (!Ok()) - { - wxFAIL_MSG( "invalid bitmap" ); - return; - } - -#ifdef wxUSE_GDK_IMLIB + m_refData = new wxBitmapRefData(); - DestroyImage(); + M_BMPDATA->m_height = image.GetHeight(); + M_BMPDATA->m_width = image.GetWidth(); + int width = image.GetWidth(); + int height = image.GetHeight(); + + // Create picture - wxCHECK_RET( M_BMPDATA->m_pixmap != NULL, "invalid bitmap" ); + GdkImage *data_image = + gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height ); - long size = (long)(M_BMPDATA->m_width)*(long)(M_BMPDATA->m_height)*(long)3; - unsigned char *data = new unsigned char[size]; - for (long i = 0; i < size; i++) data[i] = 100; + M_BMPDATA->m_pixmap = + gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ); + + // Create mask - GdkImage *image = gdk_image_get( M_BMPDATA->m_pixmap, 0, 0, M_BMPDATA->m_width, M_BMPDATA->m_height ); + GdkImage *mask_image = (GdkImage*) NULL; - long pos = 0; - for (int j = 0; j < M_BMPDATA->m_height; j++) + if (image.HasMask()) { - for (int i = 0; i < M_BMPDATA->m_width; i++) - { - XColor xcol; - xcol.pixel = gdk_image_get_pixel( image, i, j ); - Colormap cm = ((GdkColormapPrivate*)gdk_imlib_get_colormap())->xcolormap; - XQueryColor( gdk_display, cm, &xcol ); - - data[pos] = xcol.red; - data[pos+1] = xcol.green; - data[pos+2] = xcol.blue; - pos += 3; - } + unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height ); + + mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height ); + + M_BMPDATA->m_mask = new wxMask(); + M_BMPDATA->m_mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 ); } - wxCHECK_RET( M_BMPDATA->m_pixmap != NULL, "invalid bitmap" ); + // Retrieve depth + + M_BMPDATA->m_bpp = data_image->depth; + + int render_depth = 8; + if (M_BMPDATA->m_bpp > 8) render_depth = M_BMPDATA->m_bpp; + + // Render + + int r_mask = image.GetMaskRed(); + int g_mask = image.GetMaskGreen(); + int b_mask = image.GetMaskBlue(); + + unsigned char* data = image.GetData(); + + int index = 0; + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + { + int r = data[index]; + index++; + int g = data[index]; + index++; + int b = data[index]; + index++; + + if (image.HasMask()) + { + if ((r == r_mask) && (b = b_mask) && (g = g_mask)) + gdk_image_put_pixel( mask_image, x, y, 0 ); + else + gdk_image_put_pixel( mask_image, x, y, 1 ); + } + + switch (render_depth) + { + case 8: + { + GdkColormap *cmap = gtk_widget_get_default_colormap(); + GdkColor *colors = cmap->colors; + int max = 3 * (65536); + int index = -1; + + for (int i = 0; i < cmap->size; i++) + { + int rdiff = (r << 8) - colors[i].red; + int gdiff = (g << 8) - colors[i].green; + int bdiff = (b << 8) - colors[i].blue; + int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff); + if (sum < max) { index = i; max = sum; } + } + + gdk_image_put_pixel( data_image, x, y, index ); + + break; + } + case 15: + { + guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); + gdk_image_put_pixel( data_image, x, y, pixel ); + break; + } + case 16: + { + guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); + gdk_image_put_pixel( data_image, x, y, pixel ); + break; + } + case 24: + { + break; + } + case 32: + { + break; + } + default: break; + } + } + + // Blit picture - M_BMPDATA->m_image = gdk_imlib_create_image_from_data( - data, (unsigned char*)NULL, M_BMPDATA->m_width, M_BMPDATA->m_height ); + GdkGC *data_gc = gdk_gc_new( M_BMPDATA->m_pixmap ); - delete[] data; + gdk_draw_image( M_BMPDATA->m_pixmap, data_gc, data_image, 0, 0, 0, 0, width, height ); - gdk_image_destroy( image ); + gdk_image_destroy( data_image ); + gdk_gc_unref( data_gc ); - Render(); + // Blit mask -#else + if (image.HasMask()) + { + GdkGC *mask_gc = gdk_gc_new( M_BMPDATA->m_mask->m_bitmap ); - wxFAIL_MSG( "wxBitmap::RecreateImage not implemented without GdkImlib" ); + gdk_draw_image( M_BMPDATA->m_mask->m_bitmap, mask_gc, mask_image, 0, 0, 0, 0, width, height ); -#endif + gdk_image_destroy( mask_image ); + gdk_gc_unref( mask_gc ); + } + } -void wxBitmap::Render(void) +wxImage wxBitmap::ConvertToImage() const { + wxImage image; + if (!Ok()) { wxFAIL_MSG( "invalid bitmap" ); - return; + return image; } -#ifdef wxUSE_GDK_IMLIB - - if (!M_BMPDATA->m_image) RecreateImage(); + GdkImage *gdk_image = gdk_image_get( M_BMPDATA->m_pixmap, 0, 0, M_BMPDATA->m_width, M_BMPDATA->m_height ); - if (M_BMPDATA->m_pixmap) - { - gdk_imlib_free_pixmap( M_BMPDATA->m_pixmap ); - M_BMPDATA->m_pixmap = (GdkPixmap*) NULL; - } - if (M_BMPDATA->m_mask) - { - delete M_BMPDATA->m_mask; - M_BMPDATA->m_mask = (wxMask*) NULL; - } + if (!gdk_image) return image; - gdk_imlib_render( M_BMPDATA->m_image, M_BMPDATA->m_image->rgb_width, M_BMPDATA->m_image->rgb_height ); - M_BMPDATA->m_width = M_BMPDATA->m_image->rgb_width; - M_BMPDATA->m_height = M_BMPDATA->m_image->rgb_height; - M_BMPDATA->m_pixmap = gdk_imlib_move_image( M_BMPDATA->m_image ); + image.Create( M_BMPDATA->m_width, M_BMPDATA->m_height ); + char unsigned *data = image.GetData(); - wxCHECK_RET( M_BMPDATA->m_pixmap != NULL, "pixmap rendering failed" ) + int bpp = gdk_image->bpp; + GdkColormap *cmap = gtk_widget_get_default_colormap(); - GdkBitmap *mask = gdk_imlib_move_mask( M_BMPDATA->m_image ); - if (mask) + long pos = 0; + for (int j = 0; j < M_BMPDATA->m_height; j++) { - M_BMPDATA->m_mask = new wxMask(); - M_BMPDATA->m_mask->m_bitmap = mask; + for (int i = 0; i < M_BMPDATA->m_width; i++) + { + int pixel = gdk_image_get_pixel( gdk_image, i, j ); + if (bpp <= 8) + { + data[pos] = cmap->colors[pixel].red >> 8; + data[pos+1] = cmap->colors[pixel].green >> 8; + data[pos+2] = cmap->colors[pixel].blue >> 8; + } else if (bpp == 15) + { + data[pos] = (pixel >> 7) & 0xf8; + data[pos+1] = (pixel >> 3) & 0xf8; + data[pos+2] = (pixel << 3) & 0xf8; + } else if (bpp == 16) + { + data[pos] = (pixel >> 8) & 0xf8; + data[pos+1] = (pixel >> 3) & 0xfc; + data[pos+2] = (pixel << 3) & 0xf8; + } else + { + data[pos] = (pixel >> 16) & 0xff; + data[pos+1] = (pixel >> 8) & 0xff; + data[pos+2] = pixel & 0xff; + } + + pos += 3; + } } -#else + gdk_image_destroy( gdk_image ); - wxFAIL_MSG( "wxBitmap::Render not implemented without GdkImlib" ); - -#endif + return image; } + diff --git a/src/gtk1/bmpbuttn.cpp b/src/gtk1/bmpbuttn.cpp index 25968dbcd8..df7d7f6a1a 100644 --- a/src/gtk1/bmpbuttn.cpp +++ b/src/gtk1/bmpbuttn.cpp @@ -2,9 +2,8 @@ // Name: bmpbuttn.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/brush.cpp b/src/gtk1/brush.cpp index ae90ec472d..29131bbede 100644 --- a/src/gtk1/brush.cpp +++ b/src/gtk1/brush.cpp @@ -2,9 +2,8 @@ // Name: brush.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/button.cpp b/src/gtk1/button.cpp index 034e229f18..b0278860ac 100644 --- a/src/gtk1/button.cpp +++ b/src/gtk1/button.cpp @@ -2,9 +2,8 @@ // Name: button.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/checkbox.cpp b/src/gtk1/checkbox.cpp index c4aac9364a..385f9bc7c3 100644 --- a/src/gtk1/checkbox.cpp +++ b/src/gtk1/checkbox.cpp @@ -2,9 +2,8 @@ // Name: checkbox.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/choice.cpp b/src/gtk1/choice.cpp index edcf64f3e9..f6e3925ea4 100644 --- a/src/gtk1/choice.cpp +++ b/src/gtk1/choice.cpp @@ -2,9 +2,8 @@ // Name: choice.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/colour.cpp b/src/gtk1/colour.cpp index b7c2dc1176..7e57df104f 100644 --- a/src/gtk1/colour.cpp +++ b/src/gtk1/colour.cpp @@ -15,9 +15,7 @@ #include "wx/gdicmn.h" -#ifdef wxUSE_GDK_IMLIB -#include "../gdk_imlib/gdk_imlib.h" -#endif +#include "gdk/gdkprivate.h" //----------------------------------------------------------------------------- // wxColour @@ -186,19 +184,30 @@ void wxColour::CalcPixel( GdkColormap *cmap ) if ((M_COLDATA->m_hasPixel) && (M_COLDATA->m_colormap == cmap)) return; M_COLDATA->FreeColour(); -#ifdef wxUSE_GDK_IMLIB - - int r = M_COLDATA->m_color.red >> SHIFT; - int g = M_COLDATA->m_color.green >> SHIFT; - int b = M_COLDATA->m_color.blue >> SHIFT; - M_COLDATA->m_hasPixel = TRUE; - M_COLDATA->m_color.pixel = gdk_imlib_best_color_match( &r, &g, &b ); - -#else + GdkColormapPrivate *private_colormap = (GdkColormapPrivate*) cmap; + if ((private_colormap->visual->type == GDK_VISUAL_GRAYSCALE) || + (private_colormap->visual->type == GDK_VISUAL_PSEUDO_COLOR)) + { + GdkColor *colors = cmap->colors; + int max = 3 * (65536); + int index = -1; - M_COLDATA->m_hasPixel = gdk_color_alloc( cmap, &M_COLDATA->m_color ); - -#endif + for (int i = 0; i < cmap->size; i++) + { + int rdiff = (M_COLDATA->m_color.red - colors[i].red); + int gdiff = (M_COLDATA->m_color.green - colors[i].green); + int bdiff = (M_COLDATA->m_color.blue - colors[i].blue); + int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff); + if (sum < max) { index = i; max = sum; } + } + + M_COLDATA->m_hasPixel = TRUE; + M_COLDATA->m_color.pixel = index; + } + else + { + M_COLDATA->m_hasPixel = gdk_color_alloc( cmap, &M_COLDATA->m_color ); + } M_COLDATA->m_colormap = cmap; } diff --git a/src/gtk1/combobox.cpp b/src/gtk1/combobox.cpp index efe78a6f3f..59f2f9821e 100644 --- a/src/gtk1/combobox.cpp +++ b/src/gtk1/combobox.cpp @@ -2,9 +2,8 @@ // Name: combobox.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/control.cpp b/src/gtk1/control.cpp index 61bab59ecf..658ebcd8c9 100644 --- a/src/gtk1/control.cpp +++ b/src/gtk1/control.cpp @@ -2,9 +2,8 @@ // Name: control.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling, Julian Smart and Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/cursor.cpp b/src/gtk1/cursor.cpp index 7195cfa0c6..20a8d3c19e 100644 --- a/src/gtk1/cursor.cpp +++ b/src/gtk1/cursor.cpp @@ -2,9 +2,8 @@ // Name: cursor.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/data.cpp b/src/gtk1/data.cpp index 96bce38d00..815bdca347 100644 --- a/src/gtk1/data.cpp +++ b/src/gtk1/data.cpp @@ -2,8 +2,7 @@ // Name: data.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: +// Id: $id$ // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/dc.cpp b/src/gtk1/dc.cpp index 13ffab2a44..3678494de4 100644 --- a/src/gtk1/dc.cpp +++ b/src/gtk1/dc.cpp @@ -2,7 +2,6 @@ // Name: dc.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem // Licence: wxWindows licence diff --git a/src/gtk1/dcclient.cpp b/src/gtk1/dcclient.cpp index 17cd007433..a724a4d51c 100644 --- a/src/gtk1/dcclient.cpp +++ b/src/gtk1/dcclient.cpp @@ -2,9 +2,8 @@ // Name: dcclient.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -138,8 +137,6 @@ void wxPaintDC::DrawLine( long x1, long y1, long x2, long y2 ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() != wxTRANSPARENT) { gdk_draw_line( m_window, m_penGC, @@ -151,8 +148,6 @@ void wxPaintDC::CrossHair( long x, long y ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() != wxTRANSPARENT) { int w = 0; @@ -171,8 +166,6 @@ void wxPaintDC::DrawArc( long x1, long y1, long x2, long y2, double xc, double y { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - long xx1 = XLOG2DEV(x1); long yy1 = YLOG2DEV(y1); long xx2 = XLOG2DEV(x2); @@ -221,8 +214,6 @@ void wxPaintDC::DrawEllipticArc( long x, long y, long width, long height, double { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - long xx = XLOG2DEV(x); long yy = YLOG2DEV(y); long ww = m_signX * XLOG2DEVREL(width); @@ -245,8 +236,6 @@ void wxPaintDC::DrawPoint( long x, long y ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() != wxTRANSPARENT) gdk_draw_point( m_window, m_penGC, XLOG2DEV(x), YLOG2DEV(y) ); } @@ -255,8 +244,6 @@ void wxPaintDC::DrawLines( int n, wxPoint points[], long xoffset, long yoffset ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() == wxTRANSPARENT) return; for (int i = 0; i < n-1; i++) @@ -273,8 +260,6 @@ void wxPaintDC::DrawLines( wxList *points, long xoffset, long yoffset ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_pen.GetStyle() == wxTRANSPARENT) return; wxNode *node = points->First(); @@ -295,8 +280,6 @@ void wxPaintDC::DrawPolygon( int n, wxPoint points[], long xoffset, long yoffset { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (!n) return; // Nothing to draw GdkPoint *gdkpoints = new GdkPoint[n+1]; int i; @@ -322,8 +305,6 @@ void wxPaintDC::DrawPolygon( wxList *lines, long xoffset, long yoffset, int WXUN { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - int n = lines->Number(); GdkPoint *gdkpoints = new GdkPoint[n]; wxNode *node = lines->First(); @@ -356,8 +337,6 @@ void wxPaintDC::DrawRectangle( long x, long y, long width, long height ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - long xx = XLOG2DEV(x); long yy = YLOG2DEV(y); long ww = m_signX * XLOG2DEVREL(width); @@ -381,8 +360,6 @@ void wxPaintDC::DrawRoundedRectangle( long x, long y, long width, long height, d { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (radius < 0.0) radius = - radius * ((width < height) ? width : height); long xx = XLOG2DEV(x); @@ -448,8 +425,6 @@ void wxPaintDC::DrawEllipse( long x, long y, long width, long height ) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - long xx = XLOG2DEV(x); long yy = YLOG2DEV(y); long ww = m_signX * XLOG2DEVREL(width); @@ -477,8 +452,6 @@ void wxPaintDC::DrawIcon( const wxIcon &icon, long x, long y, bool useMask ) if (!icon.Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - int xx = XLOG2DEV(x); int yy = YLOG2DEV(y); @@ -506,8 +479,6 @@ bool wxPaintDC::Blit( long xdest, long ydest, long width, long height, { if (!Ok()) return FALSE; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (m_isMemDC) { wxMemoryDC* srcDC = (wxMemoryDC*)source; @@ -547,8 +518,6 @@ void wxPaintDC::DrawText( const wxString &text, long x, long y, bool WXUNUSED(us { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - GdkFont *font = m_font.GetInternalFont( m_scaleY ); x = XLOG2DEV(x); @@ -618,8 +587,6 @@ void wxPaintDC::Clear(void) { if (!Ok()) return; - if (m_isMemDC) ((wxMemoryDC*)this)->m_selected.DestroyImage(); - if (!m_isMemDC) { gdk_window_clear( m_window ); diff --git a/src/gtk1/dcmemory.cpp b/src/gtk1/dcmemory.cpp index aa8ab7a269..f346200a81 100644 --- a/src/gtk1/dcmemory.cpp +++ b/src/gtk1/dcmemory.cpp @@ -2,9 +2,8 @@ // Name: dcmemory.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -14,10 +13,6 @@ #include "wx/dcmemory.h" -#ifdef wxUSE_GDK_IMLIB -#include "../gdk_imlib/gdk_imlib.h" -#endif - //----------------------------------------------------------------------------- // wxMemoryDC //----------------------------------------------------------------------------- @@ -28,22 +23,14 @@ wxMemoryDC::wxMemoryDC(void) { m_ok = FALSE; -#ifdef wxUSE_GDK_IMLIB - m_cmap = gdk_imlib_get_colormap(); -#else - m_cmap = gdk_colormap_get_system(); -#endif + m_cmap = gtk_widget_get_default_colormap(); } wxMemoryDC::wxMemoryDC( wxDC *WXUNUSED(dc) ) { m_ok = FALSE; -#ifdef wxUSE_GDK_IMLIB - m_cmap = gdk_imlib_get_colormap(); -#else - m_cmap = gdk_colormap_get_system(); -#endif + m_cmap = gtk_widget_get_default_colormap(); } wxMemoryDC::~wxMemoryDC(void) diff --git a/src/gtk1/dcscreen.cpp b/src/gtk1/dcscreen.cpp index c3a9303751..cd47777fdb 100644 --- a/src/gtk1/dcscreen.cpp +++ b/src/gtk1/dcscreen.cpp @@ -2,9 +2,8 @@ // Name: dcscreen.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/dialog.cpp b/src/gtk1/dialog.cpp index 73ae00a02b..9bbc5f9a28 100644 --- a/src/gtk1/dialog.cpp +++ b/src/gtk1/dialog.cpp @@ -2,9 +2,8 @@ // Name: dialog.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/dnd.cpp b/src/gtk1/dnd.cpp index 458eb72641..4090bb15ec 100644 --- a/src/gtk1/dnd.cpp +++ b/src/gtk1/dnd.cpp @@ -2,8 +2,9 @@ // Name: dnd.cpp // Purpose: wxDropTarget class // Author: Robert Roebling -// Copyright: Robert Roebling -// Licence: wxWindows license +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ diff --git a/src/gtk1/filedlg.cpp b/src/gtk1/filedlg.cpp index 021946bb57..dae464b19f 100644 --- a/src/gtk1/filedlg.cpp +++ b/src/gtk1/filedlg.cpp @@ -2,9 +2,8 @@ // Name: filedlg.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/font.cpp b/src/gtk1/font.cpp index ef95c79be8..119b9cc83c 100644 --- a/src/gtk1/font.cpp +++ b/src/gtk1/font.cpp @@ -2,8 +2,7 @@ // Name: font.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: +// Id: $id$ // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/frame.cpp b/src/gtk1/frame.cpp index bead5e36e2..fbb256de87 100644 --- a/src/gtk1/frame.cpp +++ b/src/gtk1/frame.cpp @@ -2,9 +2,8 @@ // Name: frame.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/gauge.cpp b/src/gtk1/gauge.cpp index 8499339d67..30688eda35 100644 --- a/src/gtk1/gauge.cpp +++ b/src/gtk1/gauge.cpp @@ -2,9 +2,8 @@ // Name: gauge.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/notebook.cpp b/src/gtk1/notebook.cpp index 0a3b30089d..f006c328a0 100644 --- a/src/gtk1/notebook.cpp +++ b/src/gtk1/notebook.cpp @@ -2,9 +2,8 @@ // Name: notebook.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling, Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/timer.cpp b/src/gtk1/timer.cpp index 4e36a67f14..89ecf05f6d 100644 --- a/src/gtk1/timer.cpp +++ b/src/gtk1/timer.cpp @@ -2,9 +2,8 @@ // Name: timer.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gtk1/utilsgtk.cpp b/src/gtk1/utilsgtk.cpp index 3de7efc8bc..086ef60b6b 100644 --- a/src/gtk1/utilsgtk.cpp +++ b/src/gtk1/utilsgtk.cpp @@ -2,7 +2,6 @@ // Name: utils.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 // Id: $Id$ // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem // Licence: wxWindows licence diff --git a/src/gtk1/win_gtk.c b/src/gtk1/win_gtk.c index 3a999cdeff..c4e8c42101 100644 --- a/src/gtk1/win_gtk.c +++ b/src/gtk1/win_gtk.c @@ -1,10 +1,9 @@ /* /////////////////////////////////////////////////////////////////////////// // Name: wx_gtk.h -// Purpose: +// Purpose: native GTK+ widget for wxWindows // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////// */ diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index 1e6c3b6b92..eb9b9dcb84 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -2,9 +2,8 @@ // Name: window.cpp // Purpose: // Author: Robert Roebling -// Created: 01/02/97 -// Id: -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem +// Id: $id$ +// Copyright: (c) 1998 Robert Roebling, Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -- 2.45.2