diff options
author | Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> | 2008-08-19 12:28:02 -0500 |
---|---|---|
committer | Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> | 2008-08-19 12:28:02 -0500 |
commit | b53bd1cf536a3042adb884150a577b196845fd72 (patch) | |
tree | 44f13661aff7366c85ef66e6f5947fdf28b81ead | |
parent | 326e392bdcf84f9d7c27105e95c6d1963255c3b2 (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-- | .gitignore | 1 | ||||
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | cairomm/surface.cc | 104 | ||||
-rw-r--r-- | cairomm/surface.h | 60 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/test-surface.cc | 89 |
6 files changed, 254 insertions, 10 deletions
@@ -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 @@ -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; +} |