summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathon Jongsma <jonathon.jongsma@collabora.co.uk>2008-08-19 12:28:02 -0500
committerJonathon Jongsma <jonathon.jongsma@collabora.co.uk>2008-08-19 12:28:02 -0500
commitb53bd1cf536a3042adb884150a577b196845fd72 (patch)
tree44f13661aff7366c85ef66e6f5947fdf28b81ead
parent326e392bdcf84f9d7c27105e95c6d1963255c3b2 (diff)
Add sigc::slot versions of all of the functions that take a cairo_write_func_t or cairo_read_func_t
-rw-r--r--.gitignore1
-rw-r--r--ChangeLog7
-rw-r--r--cairomm/surface.cc104
-rw-r--r--cairomm/surface.h60
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/test-surface.cc89
6 files changed, 254 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore
index d52c623..05d835b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@ examples/text/text_rotate
examples/text/toy-text
tests/test-context
tests/test-font-face
+tests/test-surface
cairomm/cairommconfig.h*
cairomm/stamp-*
m4/libtool.m4
diff --git a/ChangeLog b/ChangeLog
index 623fb9a..d42b221 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-08-19 Jonathon Jongsma <jjongsma@gnome.org>
+
+ * cairomm/surface.cc:
+ * cairomm/surface.h: add sigc::slot versions of all of the functions that take
+ a cairo_write_func_t or cairo_read_func_t
+ * tests/Makefile.am: add a couple basic tests for the surfaced slot functions
+
2008-08-18 Jonathon Jongsma <jjongsma@gnome.org>
* cairomm/fontface.h: Add a bunch of documentation for the new FontFace API
diff --git a/cairomm/surface.cc b/cairomm/surface.cc
index f7393ac..57898c3 100644
--- a/cairomm/surface.cc
+++ b/cairomm/surface.cc
@@ -22,6 +22,52 @@
namespace Cairo
{
+static cairo_user_data_key_t USER_DATA_KEY_WRITE_FUNC = {0};
+static cairo_user_data_key_t USER_DATA_KEY_READ_FUNC = {0};
+
+static void
+free_slot(void* data)
+{
+ Surface::SlotWriteFunc* slot = static_cast<Surface::SlotWriteFunc*>(data);
+ delete slot;
+}
+
+static Surface::SlotWriteFunc*
+get_slot(cairo_surface_t* surface) {
+ return static_cast<Surface::SlotWriteFunc*>(cairo_surface_get_user_data(surface,
+ &USER_DATA_KEY_WRITE_FUNC));
+}
+
+static void
+set_read_slot(cairo_surface_t* surface, Surface::SlotReadFunc* slot) {
+ // the slot will automatically be freed by free_slot() when the underlying C
+ // instance is destroyed
+ cairo_surface_set_user_data(surface, &USER_DATA_KEY_READ_FUNC, slot, &free_slot);
+}
+
+static void
+set_write_slot(cairo_surface_t* surface, Surface::SlotWriteFunc* slot) {
+ // the slot will automatically be freed by free_slot() when the underlying C
+ // instance is destroyed
+ cairo_surface_set_user_data(surface, &USER_DATA_KEY_WRITE_FUNC, slot, &free_slot);
+}
+
+cairo_status_t read_func_wrapper(void* closure, unsigned char* data, unsigned int length)
+{
+ if (!closure)
+ return CAIRO_STATUS_READ_ERROR;
+ Surface::SlotReadFunc* read_func = static_cast<Surface::SlotReadFunc*>(closure);
+ return static_cast<cairo_status_t>((*read_func)(data, length));
+}
+
+cairo_status_t write_func_wrapper(void* closure, const unsigned char* data, unsigned int length)
+{
+ if (!closure)
+ return CAIRO_STATUS_WRITE_ERROR;
+ Surface::SlotWriteFunc* write_func = static_cast<Surface::SlotWriteFunc*>(closure);
+ return static_cast<cairo_status_t>((*write_func)(data, length));
+}
+
Surface::Surface(cairo_surface_t* cobject, bool has_reference)
: m_cobject(0)
{
@@ -113,6 +159,19 @@ void Surface::write_to_png(const std::string& filename)
check_status_and_throw_exception(status);
}
+void Surface::write_to_png_stream(const SlotWriteFunc& write_func)
+{
+ SlotWriteFunc* old_slot = get_slot(m_cobject);
+ if (old_slot)
+ delete old_slot;
+ SlotWriteFunc* slot_copy = new SlotWriteFunc(write_func);
+ set_write_slot(m_cobject, slot_copy);
+ ErrorStatus status = cairo_surface_write_to_png_stream(m_cobject,
+ &write_func_wrapper,
+ slot_copy /*closure*/);
+ check_status_and_throw_exception(status);
+}
+
void Surface::write_to_png(cairo_write_func_t write_func, void *closure)
{
ErrorStatus status = cairo_surface_write_to_png_stream(m_cobject, write_func, closure);
@@ -171,6 +230,16 @@ RefPtr<ImageSurface> ImageSurface::create_from_png(std::string filename)
return RefPtr<ImageSurface>(new ImageSurface(cobject, true /* has reference */));
}
+RefPtr<ImageSurface> ImageSurface::create_from_png_stream(const SlotReadFunc& read_func)
+{
+ SlotReadFunc* slot_copy = new SlotReadFunc(read_func);
+ cairo_surface_t* cobject =
+ cairo_image_surface_create_from_png_stream(&read_func_wrapper, slot_copy);
+ check_status_and_throw_exception(cairo_surface_status(cobject));
+ set_read_slot(cobject, slot_copy);
+ return RefPtr<ImageSurface>(new ImageSurface(cobject, true /* has reference */));
+}
+
RefPtr<ImageSurface> ImageSurface::create_from_png(cairo_read_func_t read_func, void *closure)
{
cairo_surface_t* cobject = cairo_image_surface_create_from_png_stream(read_func, closure);
@@ -249,6 +318,18 @@ RefPtr<PdfSurface> PdfSurface::create(cairo_write_func_t write_func, void *closu
return RefPtr<PdfSurface>(new PdfSurface(cobject, true /* has reference */));
}
+RefPtr<PdfSurface> PdfSurface::create(const SlotWriteFunc& write_func, double
+ width_in_points, double height_in_points)
+{
+ SlotWriteFunc* slot_copy = new SlotWriteFunc(write_func);
+ cairo_surface_t* cobject =
+ cairo_pdf_surface_create_for_stream(write_func_wrapper, slot_copy,
+ width_in_points, height_in_points);
+ check_status_and_throw_exception(cairo_surface_status(cobject));
+ set_write_slot(cobject, slot_copy);
+ return RefPtr<PdfSurface>(new PdfSurface(cobject, true /* has reference */));
+}
+
void PdfSurface::set_size(double width_in_points, double height_in_points)
{
cairo_pdf_surface_set_size(m_cobject, width_in_points, height_in_points);
@@ -278,6 +359,18 @@ RefPtr<PsSurface> PsSurface::create(std::string filename, double width_in_points
return RefPtr<PsSurface>(new PsSurface(cobject, true /* has reference */));
}
+RefPtr<PsSurface> PsSurface::create(const SlotWriteFunc& write_func, double
+ width_in_points, double height_in_points)
+{
+ SlotWriteFunc* slot_copy = new SlotWriteFunc(write_func);
+ cairo_surface_t* cobject =
+ cairo_ps_surface_create_for_stream(write_func_wrapper, slot_copy,
+ width_in_points, height_in_points);
+ check_status_and_throw_exception(cairo_surface_status(cobject));
+ set_write_slot(cobject, slot_copy);
+ return RefPtr<PsSurface>(new PsSurface(cobject, true /* has reference */));
+}
+
RefPtr<PsSurface> PsSurface::create(cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points)
{
cairo_surface_t* cobject = cairo_ps_surface_create_for_stream(write_func, closure, width_in_points, height_in_points);
@@ -367,6 +460,17 @@ RefPtr<SvgSurface> SvgSurface::create(std::string filename, double width_in_poin
return RefPtr<SvgSurface>(new SvgSurface(cobject, true /* has reference */));
}
+RefPtr<SvgSurface> SvgSurface::create(const SlotWriteFunc& write_func, double width_in_points, double height_in_points)
+{
+ SlotWriteFunc* slot_copy = new SlotWriteFunc(write_func);
+ cairo_surface_t* cobject =
+ cairo_svg_surface_create_for_stream(write_func_wrapper, slot_copy,
+ width_in_points, height_in_points);
+ check_status_and_throw_exception(cairo_surface_status(cobject));
+ set_write_slot(cobject, slot_copy);
+ return RefPtr<SvgSurface>(new SvgSurface(cobject, true /* has reference */));
+}
+
RefPtr<SvgSurface> SvgSurface::create(cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points)
{
cairo_surface_t* cobject = cairo_svg_surface_create_for_stream(write_func, closure, width_in_points, height_in_points);
diff --git a/cairomm/surface.h b/cairomm/surface.h
index 7043fc0..8ec0b5b 100644
--- a/cairomm/surface.h
+++ b/cairomm/surface.h
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include <sigc++/slot.h>
#include <cairomm/enums.h>
#include <cairomm/exception.h>
#include <cairomm/fontoptions.h>
@@ -59,6 +60,34 @@ namespace Cairo
class Surface
{
public:
+ /** For example:
+ * <code>
+ * ErrorStatus my_write_func(unsigned char* data, unsigned int length);
+ * </code>
+ *
+ * This is the type of function which is called when a backend needs to write
+ * data to an output stream. It is passed the data to write and the length of
+ * the data in bytes. The write function should return CAIRO_STATUS_SUCCESS if
+ * all the data was successfully written, CAIRO_STATUS_WRITE_ERROR otherwise.
+ *
+ * @param data the buffer containing the data to write
+ * @param length the amount of data to write
+ * @return the status code of the write operation
+ */
+ typedef sigc::slot<ErrorStatus, const unsigned char* /*data*/, unsigned int /*length*/> SlotWriteFunc;
+ /**
+ * This is the type of function which is called when a backend needs to read
+ * data from an input stream. It is passed the buffer to read the data into
+ * and the length of the data in bytes. The read function should return
+ * CAIRO_STATUS_SUCCESS if all the data was successfully read,
+ * CAIRO_STATUS_READ_ERROR otherwise.
+ *
+ * @param data the buffer into which to read the data
+ * @param length the amount of data to read
+ * @return the status code of the read operation
+ */
+ typedef sigc::slot<ErrorStatus, unsigned char* /*data*/, unsigned int /*length*/> SlotReadFunc;
+
/** Create a C++ wrapper for the C instance. This C++ instance should then be
* given to a RefPtr.
*
@@ -187,9 +216,12 @@ public:
*
* @param write_func The function to be called when the backend needs to
* write data to an output stream
- * @param closure closure data for the write function
+ *
+ * @since 1.8
*/
- void write_to_png(cairo_write_func_t write_func, void *closure); //TODO: Use a sigc::slot?
+ void write_to_png_stream(const SlotWriteFunc& write_func);
+ /** @deprecated Use write_to_png_stream instead */
+ void write_to_png(cairo_write_func_t write_func, void *closure);
#endif // CAIRO_HAS_PNG_FUNCTIONS
@@ -376,16 +408,17 @@ public:
static RefPtr<ImageSurface> create_from_png(std::string filename);
/** Creates a new image surface from PNG data read incrementally via the
- * read_func function.
+ * read_func function.
*
* @note For this function to be available, cairo must have been compiled
* with PNG support.
*
- * @param read_func function called to read the data of the file
- * @param closure data to pass to read_func.
- * @return a RefPtr to the new cairo_surface_t initialized with the
+ * @param read_func function called to read the data of the file
+ * @return a RefPtr to the new cairo_surface_t initialized with the
* contents of the PNG image file.
*/
+ static RefPtr<ImageSurface> create_from_png_stream(const SlotReadFunc& read_func);
+ /** @deprecated Use create_from_png_stream instead */
static RefPtr<ImageSurface> create_from_png(cairo_read_func_t read_func, void *closure);
#endif // CAIRO_HAS_PNG_FUNCTIONS
@@ -430,10 +463,13 @@ public:
*
* @param write_func The function to be called when the backend needs to
* write data to an output stream
- * @param closure closure data for the write function
* @param width_in_points The width of the PDF document in points
* @param height_in_points The height of the PDF document in points
+ *
+ * @since 1.8
*/
+ static RefPtr<PdfSurface> create(const SlotWriteFunc& write_func, double width_in_points, double height_in_points);
+ /** @deprecated */
static RefPtr<PdfSurface> create(cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points);
/**
@@ -500,10 +536,13 @@ public:
*
* @param write_func The function to be called when the backend needs to
* write data to an output stream
- * @param closure closure data for the write function
* @param width_in_points The width of the PostScript document in points
* @param height_in_points The height of the PostScript document in points
+ *
+ * @since 1.8
*/
+ static RefPtr<PsSurface> create(const SlotWriteFunc& write_func, double width_in_points, double height_in_points);
+ /** @deprecated */
static RefPtr<PsSurface> create(cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points);
/**
@@ -643,10 +682,13 @@ public:
*
* @param write_func The function to be called when the backend needs to
* write data to an output stream
- * @param closure closure data for the write function
* @param width_in_points The width of the SVG document in points
* @param height_in_points The height of the SVG document in points
+ *
+ * @since 1.8
*/
+ static RefPtr<SvgSurface> create(const SlotWriteFunc& write_func, double width_in_points, double height_in_points);
+ /** @deprecated */
static RefPtr<SvgSurface> create(cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points);
/**
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 03e58a0..9b534a5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,10 +1,11 @@
if AUTOTESTS
# build automated 'tests'
-TESTS=test-context test-font-face
+TESTS=test-context test-font-face test-surface
noinst_PROGRAMS = $(TESTS)
test_context_SOURCES=test-context.cc
test_font_face_SOURCES=test-font-face.cc
+test_surface_SOURCES=test-surface.cc
else
diff --git a/tests/test-surface.cc b/tests/test-surface.cc
new file mode 100644
index 0000000..3b3e7d0
--- /dev/null
+++ b/tests/test-surface.cc
@@ -0,0 +1,89 @@
+#include <boost/test/unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+using namespace boost::unit_test;
+#include <cairomm/surface.h>
+using namespace Cairo;
+
+static unsigned int test_slot_called = 0;
+ErrorStatus test_slot(const unsigned char* /*data*/, unsigned int /*len*/)
+{
+ test_slot_called++;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+void test_write_to_png_stream()
+{
+ RefPtr<ImageSurface> surface = ImageSurface::create(FORMAT_ARGB32, 1, 1);
+ surface->write_to_png_stream(sigc::ptr_fun(test_slot));
+ BOOST_CHECK(test_slot_called > 0);
+}
+
+void test_pdf_constructor_slot()
+{
+ test_slot_called = 0;
+ RefPtr<PdfSurface> pdf = PdfSurface::create(sigc::ptr_fun(&test_slot), 1, 1);
+ pdf->show_page();
+ pdf->finish();
+ BOOST_CHECK(test_slot_called > 0);
+}
+
+void test_ps_constructor_slot()
+{
+ test_slot_called = 0;
+ RefPtr<PsSurface> ps = PsSurface::create(sigc::ptr_fun(&test_slot), 1, 1);
+ ps->show_page();
+ ps->finish();
+ BOOST_CHECK(test_slot_called > 0);
+}
+
+void test_svg_constructor_slot()
+{
+ test_slot_called = 0;
+ RefPtr<SvgSurface> svg = SvgSurface::create(sigc::ptr_fun(&test_slot), 1, 1);
+ svg->show_page();
+ svg->finish();
+ BOOST_CHECK(test_slot_called > 0);
+}
+
+unsigned int test_read_func_called = 0;
+static ErrorStatus test_read_func(unsigned char* /*data*/, unsigned int /*len*/)
+{
+ ++test_read_func_called;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+unsigned int c_test_read_func_called = 0;
+static cairo_status_t c_test_read_func(void* /*closure*/, unsigned char* /*data*/, unsigned int /*len*/)
+{
+ ++c_test_read_func_called;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+void test_create_from_png()
+{
+ // FIXME: these cause a std::bad_alloc exception for some reason
+ RefPtr<ImageSurface> surface;
+ surface = ImageSurface::create_from_png_stream(sigc::ptr_fun(&test_read_func));
+ BOOST_CHECK(test_read_func_called > 0);
+ surface = ImageSurface::create_from_png(&c_test_read_func, NULL);
+ BOOST_CHECK(c_test_read_func_called > 0);
+}
+
+
+test_suite*
+init_unit_test_suite(int argc, char* argv[])
+{
+ // compile even with -Werror
+ if (argc && argv) {}
+
+ test_suite* test= BOOST_TEST_SUITE( "Cairo::Surface Tests" );
+
+ test->add (BOOST_TEST_CASE (&test_write_to_png_stream));
+ test->add (BOOST_TEST_CASE (&test_pdf_constructor_slot));
+ test->add (BOOST_TEST_CASE (&test_ps_constructor_slot));
+ test->add (BOOST_TEST_CASE (&test_svg_constructor_slot));
+ test->add (BOOST_TEST_CASE (&test_create_from_png));
+
+ return test;
+}