Hi,

Today I've got rid of the Gtk frontend's dependency on the xformsImage
class.  That means that the only xforms-dependence remaining in the Gtk
frontend is the placeholder dialogs.  It also removes (I think) the last
of the X-specific calls apart from Xft.

The image handling is not yet complete:
      * Only multiple-of-90-degrees rotation is supported
      * Grayscale and monochrome effects are not yet implemented.

That will be fixed in due course.

I may soon be tempted to completely rip out all remaining xforms linkage
from frontends/gtk, to make things a bit cleaner.

John
? glade/tabular.glade
Index: ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/gtk/ChangeLog,v
retrieving revision 1.142
diff -u -p -r1.142 ChangeLog
--- ChangeLog	21 Jan 2006 21:38:32 -0000	1.142
+++ ChangeLog	23 Jan 2006 23:53:28 -0000
@@ -1,3 +1,9 @@
+2006-01-23  John Spray <[EMAIL PROTECTED]>
+	* LyXGdkImage.[Ch]: replace xforms Image class
+	* Makefile.am: build LyXGdkImage
+	* GPainter.C: use new Gdk Image class
+	* lyx_gui.C: use new Gdk Image class, disable XSynchronize
+
 2006-01-21  John Spray <[EMAIL PROTECTED]>
 
 	* GBibItem.[Ch], glade/bibitem.glade: Add the bibitem dialog
Index: GPainter.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/gtk/GPainter.C,v
retrieving revision 1.17
diff -u -p -r1.17 GPainter.C
--- GPainter.C	29 Jan 2005 15:09:14 -0000	1.17
+++ GPainter.C	23 Jan 2006 23:53:28 -0000
@@ -4,6 +4,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author Huang Ying
+ * \author John Spray
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -21,12 +22,12 @@
 #include "GPainter.h"
 #include "debug.h"
 #include "GWorkArea.h"
+#include "LyXGdkImage.h"
 #include "lyxrc.h"
 #include "encoding.h"
 #include "language.h"
 #include "LColor.h"
 #include "xftFontLoader.h"
-#include "xformsImage.h"
 #include "frontends/font_metrics.h"
 #include "codeConvert.h"
 
@@ -186,12 +187,14 @@ void GPainter::arc(int x, int y, unsigne
 void GPainter::image(int x, int y, int w, int h,
 	graphics::Image const & i)
 {
-	graphics::xformsImage const & image =
-		static_cast<graphics::xformsImage const &>(i);
-	Pixmap pixmap = GDK_PIXMAP_XID(owner_.getPixmap()->gobj());
-	GC gc = GDK_GC_XGC(owner_.getGC()->gobj());
-	XCopyArea(owner_.getDisplay(), image.getPixmap(), pixmap,
-		  gc, 0, 0, w, h, x, y);
+	graphics::LyXGdkImage const & image =
+		static_cast<graphics::LyXGdkImage const &>(i);
+	Glib::RefPtr<Gdk::Pixbuf> const & pixbuf = image.pixbuf();
+	Glib::RefPtr<Gdk::Pixmap> pixmap = owner_.getPixmap();
+
+	Glib::RefPtr<Gdk::GC> gc = owner_.getGC();
+	pixmap->draw_pixbuf (gc, pixbuf, 0, 0, x, y, w, h,
+	                     Gdk::RGB_DITHER_NONE, 0, 0);
 }
 
 
Index: GWorkArea.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/gtk/GWorkArea.h,v
retrieving revision 1.15
diff -u -p -r1.15 GWorkArea.h
--- GWorkArea.h	20 Mar 2005 17:13:17 -0000	1.15
+++ GWorkArea.h	23 Jan 2006 23:53:28 -0000
@@ -103,7 +103,6 @@ private:
 	/// The pixmap overlay on the workarea
 	Glib::RefPtr<Gdk::Pixmap> workAreaPixmap_;
 	Glib::RefPtr<Gdk::GC> workAreaGC_;
-	/// the xforms-specific painter
 	GPainter painter_;
 	XftDraw * draw_;
 	ColorHandler colorHandler_;
Index: LyXGdkImage.C
===================================================================
RCS file: LyXGdkImage.C
diff -N LyXGdkImage.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ LyXGdkImage.C	23 Jan 2006 23:53:28 -0000
@@ -0,0 +1,288 @@
+/**
+ * \file LyXGdkImage.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming (original Qt version)
+ * \author John Levon (original Qt version)
+ * \author John Spray
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+// Too hard to make concept checks work with this file
+#ifdef _GLIBCXX_CONCEPT_CHECKS
+#undef _GLIBCXX_CONCEPT_CHECKS
+#endif
+#ifdef _GLIBCPP_CONCEPT_CHECKS
+#undef _GLIBCPP_CONCEPT_CHECKS
+#endif
+
+
+
+#include "LyXGdkImage.h"
+
+#include "debug.h"
+#include "format.h"
+
+#include "graphics/GraphicsParams.h"
+
+#include "support/lstrings.h"       // lowercase
+
+#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
+
+using lyx::support::lowercase;
+
+using boost::bind;
+
+using std::endl;
+using std::equal_to;
+using std::find_if;
+using std::string;
+
+
+namespace lyx {
+namespace graphics {
+
+/// Access to this class is through this static method.
+Image::ImagePtr LyXGdkImage::newImage()
+{
+	ImagePtr ptr;
+	ptr.reset(new LyXGdkImage);
+	return ptr;
+}
+
+
+/// Return the list of loadable formats.
+Image::FormatList LyXGdkImage::loadableFormats()
+{
+	static FormatList fmts;
+
+	if (!fmts.empty())
+		return fmts;
+
+	// The formats recognised by LyX
+	Formats::const_iterator begin = formats.begin();
+	Formats::const_iterator end   = formats.end();
+
+	lyxerr[Debug::GRAPHICS]
+		<< "\nThe image loader can load the following directly:\n";
+
+	Gdk::Pixbuf::SListHandle_PixbufFormat gdkformats = Gdk::Pixbuf::get_formats();
+	Gdk::Pixbuf::SListHandle_PixbufFormat::iterator it = gdkformats.begin();
+	Gdk::Pixbuf::SListHandle_PixbufFormat::iterator gdk_end = gdkformats.end();
+	
+	for (; it != gdk_end; ++it) {
+		Gdk::PixbufFormat thisformat = (*it);
+		lyxerr[Debug::GRAPHICS] << thisformat.get_name() << endl;
+
+		std::vector<Glib::ustring> extensions = thisformat.get_extensions();
+		std::vector<Glib::ustring>::const_iterator ext_end = extensions.end();
+		std::vector<Glib::ustring>::iterator ext_it = extensions.begin();
+		for (; ext_it != ext_end; ++ext_it) {
+			std::string ext = lowercase(*ext_it);
+			Formats::const_iterator fit =
+				find_if(begin, end,
+					bind(equal_to<string>(),
+					     bind(&Format::extension, _1),
+					     ext));
+			if (fit != end)
+				fmts.push_back(fit->name());
+		}
+	}
+
+	if (lyxerr.debugging()) {
+		lyxerr[Debug::GRAPHICS]
+			<< "\nOf these, LyX recognises the following formats:\n";
+
+		FormatList::const_iterator fbegin = fmts.begin();
+		FormatList::const_iterator fend   = fmts.end();
+		for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
+			if (fit != fbegin)
+				lyxerr[Debug::GRAPHICS] << ", ";
+			lyxerr[Debug::GRAPHICS] << *fit;
+		}
+		lyxerr[Debug::GRAPHICS] << '\n' << endl;
+	}
+
+	return fmts;
+}
+
+
+LyXGdkImage::LyXGdkImage()
+	: Image()
+{
+}
+
+
+LyXGdkImage::LyXGdkImage(LyXGdkImage const & other)
+	: Image(other), original_(other.original_),
+	  transformed_(other.transformed_)
+{}
+
+
+Image * LyXGdkImage::clone_impl() const
+{
+	return new LyXGdkImage(*this);
+}
+
+
+unsigned int LyXGdkImage::getWidth_impl() const
+{
+	return transformed_->get_width();
+}
+
+
+unsigned int LyXGdkImage::getHeight_impl() const
+{
+	return transformed_->get_height();
+}
+
+
+void LyXGdkImage::load_impl(string const & filename)
+{
+	if (original_) {
+		lyxerr[Debug::GRAPHICS]
+			<< "Image is loaded already!" << endl;
+		finishedLoading(false);
+		return;
+	}
+
+	original_ = Gdk::Pixbuf::create_from_file(filename);
+
+	if (!original_){
+		lyxerr[Debug::GRAPHICS]
+			<< "Unable to open image" << endl;
+		finishedLoading(false);
+		return;
+	}
+
+	transformed_ = original_;
+	finishedLoading(true);
+}
+
+/*
+namespace {
+
+// This code is taken from KImageEffect::toGray
+QImage & toGray(QImage & img)
+{
+	if (img.width() == 0 || img.height() == 0)
+		return img;
+
+	int const pixels = img.depth() > 8 ?
+		img.width() * img.height() : img.numColors();
+
+	unsigned int * const data = img.depth() > 8 ?
+		(unsigned int *)img.bits() :
+		(unsigned int *)img.colorTable();
+
+	for(int i = 0; i < pixels; ++i){
+		int const val = qGray(data[i]);
+		data[i] = qRgba(val, val, val, qAlpha(data[i]));
+	}
+	return img;
+}
+
+} // namespace anon
+*/
+
+bool LyXGdkImage::setPixmap_impl(Params const & params)
+{
+	if (!original_ || params.display == NoDisplay)
+		return false;
+
+	// TODO: implement grayscale and monochrome
+	switch (params.display) {
+	case GrayscaleDisplay: {
+		//toGray(transformed_);
+		break;
+	}
+
+	case MonochromeDisplay: {
+		//transformed_.convertDepth(transformed_.depth(), Qt::MonoOnly);
+		break;
+	}
+
+	default:
+		break;
+	}
+
+	return true;
+}
+
+
+void LyXGdkImage::clip_impl(Params const & params)
+{
+	if (!transformed_)
+		return;
+
+	if (params.bb.empty())
+		// No clipping is necessary.
+		return;
+
+	int const new_width  = params.bb.xr - params.bb.xl;
+	int const new_height = params.bb.yt - params.bb.yb;
+
+	// No need to check if the width, height are > 0 because the
+	// Bounding Box would be empty() in this case.
+	if (new_width > original_->get_width() || new_height > original_->get_height()) {
+		// Bounds are invalid.
+		return;
+	}
+
+	if (new_width == original_->get_width() && new_height == original_->get_height())
+		return;
+
+	int const xoffset_l = params.bb.xl;
+	int const yoffset_t = (original_->get_height() > int(params.bb.yt) ?
+			       original_->get_height() - params.bb.yt : 0);
+
+	transformed_ = Gdk::Pixbuf::create_subpixbuf(original_,
+		xoffset_l, yoffset_t, new_width, new_height);
+}
+
+
+void LyXGdkImage::rotate_impl(Params const & params)
+{
+	if (!transformed_)
+		return;
+
+	if (!params.angle)
+		return;
+
+	// TODO: allow free rotation
+	Gdk::PixbufRotation rotation = Gdk::PIXBUF_ROTATE_NONE;
+	if (params.angle == 90.0)
+		rotation = Gdk::PIXBUF_ROTATE_COUNTERCLOCKWISE;
+	else if (params.angle == 180.0)
+		rotation = Gdk::PIXBUF_ROTATE_UPSIDEDOWN;
+	else if (params.angle == 270.0)
+		rotation = Gdk::PIXBUF_ROTATE_CLOCKWISE;
+		
+		
+	transformed_ = transformed_->rotate_simple(rotation);
+}
+
+
+void LyXGdkImage::scale_impl(Params const & params)
+{
+	if (!transformed_)
+		return;
+
+	unsigned int width;
+	unsigned int height;
+	boost::tie(width, height) = getScaledDimensions(params);
+
+	if (width == getWidth() && height == getHeight())
+		return;
+
+	transformed_ = transformed_->scale_simple(
+		width, height, Gdk::INTERP_BILINEAR);
+}
+
+} // namespace graphics
+} // lyx
Index: LyXGdkImage.h
===================================================================
RCS file: LyXGdkImage.h
diff -N LyXGdkImage.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ LyXGdkImage.h	23 Jan 2006 23:53:28 -0000
@@ -0,0 +1,76 @@
+// -*- C++ -*-
+/**
+ * \file GdkImage.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming (original Qt version)
+ * \author John Levon (original Qt version)
+ * \author John Spray
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef LYXGDKIMAGE_H
+#define LYXGDKIMAGE_H
+
+
+#include "graphics/GraphicsImage.h"
+
+#include <gdkmm.h>
+
+namespace lyx {
+namespace graphics {
+
+class LyXGdkImage : public Image {
+public:
+	/// Access to this class is through this static method.
+	static ImagePtr newImage();
+
+	/// Return the list of loadable formats.
+	static FormatList loadableFormats();
+
+	/// Retrieve the buffered pixmap.
+	Glib::RefPtr<Gdk::Pixbuf> const & pixbuf() const {return transformed_;}
+
+private:
+	/// Create a copy
+	virtual Image * clone_impl() const;
+	/// Get the image width
+	virtual unsigned int getWidth_impl() const;
+	/// Get the image height
+	virtual unsigned int getHeight_impl() const;
+	// FIXME Is the image drawable ?
+	virtual bool isDrawable_impl() const { return true; }
+	/**
+	 * Load the image file into memory.
+	 * The process is asynchronous, so this method starts the loading.
+	 * When finished, the Image::finishedLoading signal is emitted.
+	 */
+	virtual void load_impl(std::string const & filename);
+	/**
+	 * Finishes the process of modifying transformed_, using
+	 * \c params to decide on color, grayscale etc.
+	 * \returns true if successful.
+	 */
+	virtual bool setPixmap_impl(Params const & params);
+	/// Clip the image using params.
+	virtual void clip_impl(Params const & params);
+	/// Rotate the image using params.
+	virtual void rotate_impl(Params const & params);
+	/// Scale the image using params.
+	virtual void scale_impl(Params const & params);
+
+	/// Access to the class is through newImage() and clone.
+	LyXGdkImage();
+	///
+	LyXGdkImage(LyXGdkImage const &);
+
+	Glib::RefPtr<Gdk::Pixbuf> original_;
+	Glib::RefPtr<Gdk::Pixbuf> transformed_;
+};
+
+} // namespace graphics
+} // namespace lyx
+
+#endif // LYXGDKIMAGE_H
Index: Makefile.am
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/gtk/Makefile.am,v
retrieving revision 1.45
diff -u -p -r1.45 Makefile.am
--- Makefile.am	21 Jan 2006 20:06:37 -0000	1.45
+++ Makefile.am	23 Jan 2006 23:53:28 -0000
@@ -116,6 +116,8 @@ libgtk_la_SOURCES = \
 	GtkmmX.h \
 	IdSc.C \
 	IdSc.h \
+	LyXGdkImage.C \
+	LyXGdkImage.h \
 	LyXKeySymFactory.C \
 	LyXScreenFactory.C \
 	WorkAreaFactory.C \
Index: lyx_gui.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/gtk/lyx_gui.C,v
retrieving revision 1.27
diff -u -p -r1.27 lyx_gui.C
--- lyx_gui.C	25 Jul 2005 13:45:17 -0000	1.27
+++ lyx_gui.C	23 Jan 2006 23:53:28 -0000
@@ -50,7 +50,6 @@
 
 //just for xforms
 #include "lyx_forms.h"
-#include "xformsImage.h"
 #include "xforms_helpers.h"
 
 #include "support/lyxlib.h"
@@ -60,6 +59,8 @@
 
 #include <gtkmm.h>
 
+#include "LyXGdkImage.h"
+
 #include <boost/bind.hpp>
 #include <boost/function.hpp>
 #include <boost/shared_ptr.hpp>
@@ -192,11 +193,6 @@ void parse_init_xforms(int & argc, char 
 
 	XSetErrorHandler(LyX_XErrHandler);
 
-	using namespace lyx::graphics;
-
-	// connect the image loader based on the xforms library
-	Image::newImage = boost::bind(&xformsImage::newImage);
-	Image::loadableFormats = boost::bind(&xformsImage::loadableFormats);
 }
 
 
@@ -206,6 +202,10 @@ void lyx_gui::parse_init(int & argc, cha
 
 	parse_init_xforms(argc, argv);
 
+	using namespace lyx::graphics;
+	Image::newImage = boost::bind(&LyXGdkImage::newImage);
+	Image::loadableFormats = boost::bind(&LyXGdkImage::loadableFormats);
+
 	locale_init();
 
 	// must do this /before/ lyxrc gets read
@@ -335,7 +335,7 @@ void lyx_gui::start(string const & batch
 {
 	start_xforms();
 	// just for debug
-	XSynchronize(getDisplay(), true);
+	//XSynchronize(getDisplay(), true);
 
 	boost::shared_ptr<GView> view_ptr(new GView);
 	LyX::ref().addLyXView(view_ptr);

Reply via email to