summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathon Jongsma <jjongsma@gnome.org>2008-12-08 22:31:56 -0600
committerJonathon Jongsma <jjongsma@gnome.org>2008-12-08 22:31:56 -0600
commit3be1dc30c7ff2562eb19bcab278610d44e9ba13c (patch)
tree9e221351333a4583cc222caa6aae315600d7e777
parentb1d01ff7dadf2418bb06b3bf58a3847616769e0e (diff)
UserFontFace redesign to use virtual functions
* cairomm/fontface.cc: * cairomm/fontface.h: Change UserFontFace implementation to a vfunc-based implementation rather than requiring people to supply callbacks at runtime as sigc::slot objects. This was requested by Ian Britten on the mailing list and was my original plan but ran into issues in my original implementation. This isn't a fully-working implementation yet, but I think I can overcome the issues now, so I'm moving forward on the redesign. * tests/test-font-face.cc: disable UserFontFace tests for now Conflicts: ChangeLog cairomm/fontface.cc cairomm/fontface.h
-rw-r--r--ChangeLog11
-rw-r--r--cairomm/fontface.cc156
-rw-r--r--cairomm/fontface.h142
-rw-r--r--tests/test-font-face.cc4
4 files changed, 112 insertions, 201 deletions
diff --git a/ChangeLog b/ChangeLog
index 2d51c51..3934456 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2008-12-07 Jonathon Jongsma <jonathon@quotidian.org>
+
+ * cairomm/fontface.cc:
+ * cairomm/fontface.h: Change UserFontFace implementation to a vfunc-based
+ implementation rather than requiring people to supply callbacks at runtime as
+ sigc::slot objects. This was requested by Ian Britten on the mailing list and
+ was my original plan but ran into issues in my original implementation. This
+ isn't a fully-working implementation yet, but I think I can overcome the
+ issues now, so I'm moving forward on the redesign.
+ * tests/test-font-face.cc: disable UserFontFace tests for now
+
2008-12-05 Jonathon Jongsma <jonathon@quotidian.org>
* cairomm/scaledfont.cc: Fix an error in ScaledFont::get_font_face() where
diff --git a/cairomm/fontface.cc b/cairomm/fontface.cc
index 2246a1b..840a762 100644
--- a/cairomm/fontface.cc
+++ b/cairomm/fontface.cc
@@ -107,22 +107,13 @@ FontWeight ToyFontFace::get_weight() const
//*************************//
// UserFont Implementation //
//*************************//
-//This is defined here, so we can change it later without breaking public ABI.
-class UserFontFace::PrivateData
-{
-public:
- SlotInit m_init_slot;
- SlotUnicodeToGlyph m_unicode_to_glyph_slot;
- SlotRenderGlyph m_render_glyph_slot;
- SlotTextToGlyphs m_text_to_glyphs_slot;
-};
static const cairo_user_data_key_t user_font_key = {0};
static void
log_uncaught_exception(const char* message = 0)
{
- std::cerr << "*** cairomm: Uncaught exception in slot callback";
+ std::cerr << "*** cairomm: Uncaught exception in UserFont callback";
if(message)
std::cerr << ": " << message;
@@ -131,8 +122,8 @@ log_uncaught_exception(const char* message = 0)
cairo_status_t
UserFontFace::init_cb(cairo_scaled_font_t* scaled_font,
- cairo_t *cr,
- cairo_font_extents_t* metrics)
+ cairo_t *cr,
+ cairo_font_extents_t* metrics)
{
cairo_font_face_t* face = cairo_scaled_font_get_font_face(scaled_font);
// we've stored a pointer to the wrapper object in the C object's user_data
@@ -140,13 +131,13 @@ UserFontFace::init_cb(cairo_scaled_font_t* scaled_font,
static_cast<UserFontFace*>(cairo_font_face_get_user_data(face,
&user_font_key));
- if(instance && instance->m_priv && instance->m_priv->m_init_slot)
+ if(instance)
{
try
{
- return (instance->m_priv->m_init_slot)(RefPtr<ScaledFont>(new ScaledFont(scaled_font)),
- RefPtr<Context>(new Context(cr)),
- static_cast<FontExtents&>(*metrics));
+ return instance->init(RefPtr<ScaledFont>(new ScaledFont(scaled_font)),
+ RefPtr<Context>(new Context(cr)),
+ static_cast<FontExtents&>(*metrics));
}
catch(const std::exception& ex)
{
@@ -162,22 +153,31 @@ UserFontFace::init_cb(cairo_scaled_font_t* scaled_font,
return CAIRO_STATUS_USER_FONT_ERROR;
}
+ErrorStatus
+UserFontFace::init(const RefPtr<ScaledFont>& /*scaled_font*/,
+ const RefPtr<Context>& /*cr*/,
+ FontExtents& /*extents*/)
+{
+ // fallback behavior is to not do anything, just claim success
+ return CAIRO_STATUS_SUCCESS;
+}
+
cairo_status_t
UserFontFace::unicode_to_glyph_cb(cairo_scaled_font_t *scaled_font,
- unsigned long unicode,
- unsigned long *glyph)
+ unsigned long unicode,
+ unsigned long *glyph)
{
cairo_font_face_t* face = cairo_scaled_font_get_font_face(scaled_font);
// we've stored a pointer to the wrapper object in the C object's user_data
UserFontFace* instance =
static_cast<UserFontFace*>(cairo_font_face_get_user_data(face,
&user_font_key));
- if(instance && instance->m_priv && instance->m_priv->m_unicode_to_glyph_slot)
+ if(instance)
{
try
{
- return (instance->m_priv->m_unicode_to_glyph_slot)(RefPtr<ScaledFont>(new ScaledFont(scaled_font)),
- unicode, *glyph);
+ return instance->unicode_to_glyph(RefPtr<ScaledFont>(new ScaledFont(scaled_font)),
+ unicode, *glyph);
}
catch(const std::exception& ex)
{
@@ -193,15 +193,25 @@ UserFontFace::unicode_to_glyph_cb(cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_USER_FONT_ERROR;
}
+ErrorStatus
+UserFontFace::unicode_to_glyph(const RefPtr<ScaledFont>& /*scaled_font*/,
+ unsigned long unicode,
+ unsigned long& glyph)
+{
+ // fallback behavior is just to map 1:1
+ glyph = unicode;
+ return CAIRO_STATUS_SUCCESS;
+}
+
cairo_status_t
UserFontFace::text_to_glyphs_cb(cairo_scaled_font_t *scaled_font,
- const char *utf8,
- int utf8_len,
- cairo_glyph_t **glyphs,
- int *num_glyphs,
- cairo_text_cluster_t **clusters,
- int *num_clusters,
- cairo_text_cluster_flags_t *cluster_flags)
+ const char *utf8,
+ int utf8_len,
+ cairo_glyph_t **glyphs,
+ int *num_glyphs,
+ cairo_text_cluster_t **clusters,
+ int *num_clusters,
+ cairo_text_cluster_flags_t *cluster_flags)
{
cairo_font_face_t* face = cairo_scaled_font_get_font_face(scaled_font);
// we've stored a pointer to the wrapper object in the C object's user_data
@@ -209,7 +219,7 @@ UserFontFace::text_to_glyphs_cb(cairo_scaled_font_t *scaled_font,
static_cast<UserFontFace*>(cairo_font_face_get_user_data(face,
&user_font_key));
- if(instance && instance->m_priv && instance->m_priv->m_text_to_glyphs_slot)
+ if(instance)
{
try
{
@@ -219,12 +229,9 @@ UserFontFace::text_to_glyphs_cb(cairo_scaled_font_t *scaled_font,
TextClusterFlags local_flags = static_cast<TextClusterFlags>(0);
ErrorStatus status =
- (instance->m_priv->m_text_to_glyphs_slot)(RefPtr<ScaledFont>(new
- ScaledFont(scaled_font)),
- utf8_str,
- glyph_v,
- cluster_v,
- local_flags);
+ instance->text_to_glyphs(RefPtr<ScaledFont>(new
+ ScaledFont(scaled_font)),
+ utf8_str, glyph_v, cluster_v, local_flags);
// TODO: we re-allocate a new array and pass it back to the caller since
// cairo will free the the returned array. It sucks to do this excessive
@@ -273,24 +280,36 @@ UserFontFace::text_to_glyphs_cb(cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_USER_FONT_ERROR;
}
+ErrorStatus
+UserFontFace::text_to_glyphs(const RefPtr<ScaledFont>& /*scaled_font*/,
+ const std::string& /*utf8*/,
+ std::vector<Glyph>& /*glyphs*/,
+ std::vector<TextCluster>& /*clusters*/,
+ TextClusterFlags& /*cluster_flags*/)
+{
+ // FIXME: default implementation should return -1 for num_glyphs, but there's not
+ // really any way to do that with the current interface
+ return CAIRO_STATUS_SUCCESS;
+}
+
cairo_status_t
UserFontFace::render_glyph_cb(cairo_scaled_font_t *scaled_font,
- unsigned long glyph,
- cairo_t *cr,
- cairo_text_extents_t *metrics)
+ unsigned long glyph,
+ cairo_t *cr,
+ cairo_text_extents_t *metrics)
{
cairo_font_face_t* face = cairo_scaled_font_get_font_face(scaled_font);
// we've stored a pointer to the wrapper object in the C object's user_data
UserFontFace* instance =
static_cast<UserFontFace*>(cairo_font_face_get_user_data(face,
&user_font_key));
- if(instance && instance->m_priv && instance->m_priv->m_render_glyph_slot)
+ if(instance)
{
try
{
- return (instance->m_priv->m_render_glyph_slot)(RefPtr<ScaledFont>(new ScaledFont(scaled_font)),
- glyph, RefPtr<Context>(new Context(cr)),
- static_cast<TextExtents&>(*metrics));
+ return instance->render_glyph(RefPtr<ScaledFont>(new ScaledFont(scaled_font)),
+ glyph, RefPtr<Context>(new Context(cr)),
+ static_cast<TextExtents&>(*metrics));
}
catch(const std::exception& ex)
{
@@ -306,14 +325,11 @@ UserFontFace::render_glyph_cb(cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_USER_FONT_ERROR;
}
-RefPtr<UserFontFace> UserFontFace::create()
-{
- return RefPtr<UserFontFace>(new UserFontFace());
-}
+// no default implementation for UserFontFace::render_glyph(), user must
+// implement it
UserFontFace::UserFontFace()
- : FontFace(cairo_user_font_face_create(), true /* has reference */),
- m_priv(new PrivateData())
+ : FontFace(cairo_user_font_face_create(), true /* has reference */)
{
check_status_and_throw_exception(cairo_font_face_status(m_cobject));
@@ -322,56 +338,16 @@ UserFontFace::UserFontFace()
// can't be a class member), we can get a reference to the wrapper class
cairo_font_face_set_user_data(m_cobject, &user_font_key,
(void*)this, (cairo_destroy_func_t) NULL);
-}
-
-UserFontFace::~UserFontFace()
-{
- delete m_priv;
-}
-
-void UserFontFace::set_init_func(const SlotInit& init_func)
-{
- if(!m_priv)
- return;
-
- // copy the new slot
- m_priv->m_init_slot = init_func;
-
- // register it with cairo
cairo_user_font_face_set_init_func(cobj(), init_cb);
-}
-
-void UserFontFace::set_render_glyph_func(const SlotRenderGlyph& render_glyph_func)
-{
- if(!m_priv)
- return;
-
- // copy the slot
- m_priv->m_render_glyph_slot = render_glyph_func;
cairo_user_font_face_set_render_glyph_func(cobj(), render_glyph_cb);
-}
-
-void UserFontFace::set_unicode_to_glyph_func(const SlotUnicodeToGlyph& unicode_to_glyph_func)
-{
- if(!m_priv)
- return;
-
- // copy the slot
- m_priv->m_unicode_to_glyph_slot = unicode_to_glyph_func;
cairo_user_font_face_set_unicode_to_glyph_func(cobj(), unicode_to_glyph_cb);
+ cairo_user_font_face_set_text_to_glyphs_func(cobj(), text_to_glyphs_cb);
}
-void UserFontFace::set_text_to_glyphs_func(const SlotTextToGlyphs& text_to_glyphs_func)
+UserFontFace::~UserFontFace()
{
- if(!m_priv)
- return;
-
- // copy the slot
- m_priv->m_text_to_glyphs_slot = text_to_glyphs_func;
- cairo_user_font_face_set_text_to_glyphs_func(cobj(), text_to_glyphs_cb);
}
-
#ifdef CAIRO_HAS_FT_FONT
RefPtr<FtFontFace>
diff --git a/cairomm/fontface.h b/cairomm/fontface.h
index 810f404..5001e28 100644
--- a/cairomm/fontface.h
+++ b/cairomm/fontface.h
@@ -33,7 +33,6 @@
/* end OS X */
-#include <sigc++/slot.h>
#include <cairo.h>
#ifdef CAIRO_HAS_FT_FONT
#include <cairo-ft.h>
@@ -157,7 +156,12 @@ public:
virtual ~UserFontFace();
+ /*
static RefPtr<UserFontFace> create();
+ static RefPtr<UserFontFace> create(cairo_font_face_t* cobject, bool has_reference = false);
+ */
+
+protected:
/** A SlotInit slot is called when a ScaledFont needs
* to be created for a UserFontFace.
@@ -190,32 +194,12 @@ public:
* @param extents font extents to fill in, in font space.
* @return CAIRO_STATUS_SUCCESS upon success, or CAIRO_STATUS_USER_FONT_ERROR or any other error status on error.
*/
- typedef sigc::slot<ErrorStatus,
- const RefPtr<ScaledFont>&,
- const RefPtr<Context>&,
- FontExtents&> SlotInit;
-
- /** Sets the scaled-font initialization function of a user-font.
- * See SlotInit for details of how the callback works.
- *
- * The font-face should not be immutable or a CAIRO_STATUS_USER_FONT_IMMUTABLE
- * error will occur. A user font-face is immutable as soon as a scaled-font
- * is created from it.
- *
- * @param init_func The init callback.
- *
- * @since 1.8
- */
- void set_init_func(const SlotInit& init_func);
+ virtual ErrorStatus init(const RefPtr<ScaledFont>& scaled_font,
+ const RefPtr<Context>& cr,
+ FontExtents& extents);
- /** A SlotUnicodeToGlyph slot is called to convert an
- * input Unicode character to a single glyph. This is used by the
- * Context::show_text() operation.
- *
- * For example:
- * <code>
- * ErrorStatus my_unicode_to_glyph_func(const RefPtr<ScaledFont>& scaled_font, unsigned long unicode, unsigned long& glyph);
- * </code>
+ /** unicode_to_glyph is called to convert an input Unicode character to a
+ * single glyph. This is used by the Context::show_text() operation.
*
* This callback is used to provide the same functionality as the
* text_to_glyphs callback does (see SlotTextToGlyphs) but has much less
@@ -242,34 +226,12 @@ public:
* @return CAIRO_STATUS_SUCCESS upon success, or CAIRO_STATUS_USER_FONT_ERROR
* or any other error status on error.
*/
- typedef sigc::slot<ErrorStatus,
- const RefPtr<ScaledFont>&,
- unsigned long /*unicode*/,
- unsigned long& /*glyph*/> SlotUnicodeToGlyph;
-
-
- /** Sets the unicode-to-glyph conversion function of a user-font.
- * See SlotUnicodeToGlyph for details of how the callback
- * works.
- *
- * The font-face should not be immutable or a CAIRO_STATUS_USER_FONT_IMMUTABLE
- * error will occur. A user font-face is immutable as soon as a scaled-font
- * is created from it.
- *
- * @param unicode_to_glyph_func The unicode_to_glyph callback.
- *
- * @since 1.8
- */
- void set_unicode_to_glyph_func(const SlotUnicodeToGlyph& unicode_to_glyph_func);
+ virtual ErrorStatus unicode_to_glyph(const RefPtr<ScaledFont>& scaled_font,
+ unsigned long unicode,
+ unsigned long& glyph);
- /** A SlotRenderGlyph slot is called when a user
- * ScaledFont needs to render a glyph.
- *
- * For example:
- * <code>
- * ErrorStatus my_render_glyph_func(const RefPtr<ScaledFont>& scaled_font, unsigned long glyph, const RefPtr<Context>& cr, TextExtents& metrics);
- * </code>
+ /** render_glyph is called when a user ScaledFont needs to render a glyph.
*
* The callback is mandatory, and expected to draw the glyph with code glyph
* to the Context cr. cr is prepared such that the glyph drawing is done
@@ -301,47 +263,28 @@ public:
* @param glyph glyph code to render.
* @param cr cairo context to draw to, in font space.
* @param extents glyph extents to fill in, in font space.
- * @return CAIRO_STATUS_SUCCESS upon success, or CAIRO_STATUS_USER_FONT_ERROR or any other error status on error.
- */
- typedef sigc::slot<ErrorStatus,
- const RefPtr<ScaledFont>&,
- unsigned long /*glyph*/,
- const RefPtr<Context>&,
- TextExtents& /*metrics*/> SlotRenderGlyph;
-
- /** Sets the glyph rendering function of a user-font.
- * See SlotRenderGlyph for details of how the callback
- * works.
- *
- * The font-face should not be immutable or a CAIRO_STATUS_USER_FONT_IMMUTABLE
- * error will occur. A user font-face is immutable as soon as a scaled-font
- * is created from it.
- *
- * The render_glyph callback is the only mandatory callback of a user-font.
- * If the callback is %NULL and a glyph is tried to be rendered using
- * @font_face, a CAIRO_STATUS_USER_FONT_ERROR will occur.
- *
- * @param render_glyph_func The render_glyph callback.
- *
- * @since 1.8
+ * @return CAIRO_STATUS_SUCCESS upon success, or CAIRO_STATUS_USER_FONT_ERROR
+ * or any other error status on error.
*/
- void set_render_glyph_func(const SlotRenderGlyph& render_glyph_func);
+ virtual ErrorStatus render_glyph(const RefPtr<ScaledFont>& scaled_font,
+ unsigned long glyph,
+ const RefPtr<Context>& cr,
+ TextExtents& metrics) = 0;
- /** A SlotTextToGlyphs slot is called to convert input text to an array of glyphs. This is used by the
- * Cairo::Context::show_text() operation.
+ /** text_to_glyphs is called to convert input text to an array of glyphs. This
+ * is used by the Cairo::Context::show_text() operation.
*
- * Using this callback the user-font has full control on glyphs and their
+ * By implementing this virtual function the user-font has full control on glyphs and their
* positions. That means, it allows for features like ligatures and kerning,
* as well as complex <firstterm>shaping</firstterm> required for scripts like
* Arabic and Indic.
*
- * The callback should populate the glyph indices and
- * positions (in font space) assuming that the text is to be shown at the
- * origin.
+ * This virtual function should populate the glyph indices and positions (in
+ * font space) assuming that the text is to be shown at the origin.
*
* The callback is optional. If not set, the unicode_to_glyph callback
- * is tried. See SlotUnicodeToGlyph.
+ * is tried.
*
* Note: While cairo does not impose any limitation on glyph indices,
* some applications may assume that a glyph index fits in a 16-bit
@@ -361,40 +304,17 @@ public:
*
* Since: 1.8
**/
- typedef sigc::slot<ErrorStatus,
- const RefPtr<ScaledFont>&,
- const std::string& /*utf8*/,
- std::vector<Glyph>& /*glyphs*/,
- std::vector<TextCluster>& /*clusters*/,
- TextClusterFlags& /*cluster_flags*/> SlotTextToGlyphs;
-
- /** Sets the text-to-glyphs conversion function of a user-font.
- * See SlotTextToGlyphs for details of how the callback
- * works.
- *
- * The font-face should not be immutable or a CAIRO_STATUS_USER_FONT_IMMUTABLE
- * error will occur. A user font-face is immutable as soon as a scaled-font
- * is created from it.
- *
- * @param text_to_glyphs_func The text_to_glyphs callback.
- *
- * @since 1.8
- */
- void set_text_to_glyphs_func(const SlotTextToGlyphs& text_to_glyphs_func);
+ virtual ErrorStatus text_to_glyphs(const RefPtr<ScaledFont>& scaled_font,
+ const std::string& utf8,
+ std::vector<Glyph>& glyphs,
+ std::vector<TextCluster>& clusters,
+ TextClusterFlags& cluster_flags);
- // Like gtkmm, we don't have get_*_func() methods. They would not be very useful.
- //TODO: Add unset_*_func() methods, to match the use of NULL in the C API?
-
-
-protected:
UserFontFace();
private:
- struct PrivateData;
- PrivateData* m_priv;
-
static cairo_status_t
init_cb(cairo_scaled_font_t* scaled_font,
cairo_t *cr,
diff --git a/tests/test-font-face.cc b/tests/test-font-face.cc
index 0ebe91e..85ccccf 100644
--- a/tests/test-font-face.cc
+++ b/tests/test-font-face.cc
@@ -46,6 +46,7 @@ void test_toy_getters ()
BOOST_CHECK_EQUAL (Cairo::FONT_TYPE_TOY, toy->get_type());
}
+#if 0
void test_user_font_create()
{
Cairo::RefPtr<Cairo::UserFontFace> font = Cairo::UserFontFace::create();
@@ -280,6 +281,7 @@ void test_user_font_replace_callback()
BOOST_CHECK (init2_call_count > 0);
BOOST_CHECK_EQUAL (init_call_count, 0);
}
+#endif // UserFont disabled
#ifdef CAIRO_HAS_FT_FONT
void test_ft_font_face()
@@ -344,12 +346,14 @@ init_unit_test_suite(int argc, char* argv[])
test->add (BOOST_TEST_CASE (&test_create_toy));
test->add (BOOST_TEST_CASE (&test_toy_getters));
+ /*
test->add (BOOST_TEST_CASE (&test_user_font_create));
test->add (BOOST_TEST_CASE (&test_user_font_callbacks_ptr));
test->add (BOOST_TEST_CASE (&test_user_font_callbacks_ptr_text));
test->add (BOOST_TEST_CASE (&test_user_font_callbacks_mem));
test->add (BOOST_TEST_CASE (&test_user_font_callbacks_exception));
test->add (BOOST_TEST_CASE (&test_user_font_replace_callback));
+ */
#ifdef CAIRO_HAS_FT_FONT
test->add (BOOST_TEST_CASE (&test_ft_font_face));
#endif // CAIRO_HAS_FT_FONT