Blame tests/test-user-font.cc

Packit 908522
// vim: ts=2 sw=2 et
Packit 908522
/*
Packit 908522
 * These tests are of limited usefulness.  In fact, you might even say that
Packit 908522
 * they're not really tests at all.  But I felt that it would be useful to have
Packit 908522
 * some basic usage of most functions just to verify that things compile and
Packit 908522
 * work generally
Packit 908522
 */
Packit 908522
Packit 908522
#include <cfloat>
Packit 908522
#include <stdexcept>
Packit 908522
#include <boost/test/unit_test.hpp>
Packit 908522
#include <boost/test/test_tools.hpp>
Packit 908522
#include <boost/test/floating_point_comparison.hpp>
Packit 908522
using namespace boost::unit_test;
Packit 908522
#include <cairomm/fontface.h>
Packit 908522
#include <cairomm/scaledfont.h>
Packit 908522
#include <cairomm/surface.h>
Packit 908522
#include <cairomm/context.h>
Packit 908522
Packit 908522
using namespace Cairo;
Packit 908522
Packit 908522
// little utility helper classes
Packit 908522
struct TestSetup
Packit 908522
{
Packit 908522
  TestSetup()
Packit 908522
  {
Packit 908522
    surface = ImageSurface::create(Cairo::FORMAT_ARGB32, 100, 100);
Packit 908522
    cr = Cairo::Context::create(surface);
Packit 908522
  }
Packit 908522
Packit 908522
  RefPtr<Context> cr;
Packit 908522
  RefPtr<Surface> surface;
Packit 908522
};
Packit 908522
Packit 908522
// a no-op-render user font base class
Packit 908522
class NullRenderUserFont : public UserFontFace
Packit 908522
{
Packit 908522
public:
Packit 908522
  ErrorStatus
Packit 908522
    render_glyph(const RefPtr<ScaledFont>& /*scaled_font*/,
Packit 908522
                 unsigned long /*glyph*/,
Packit 908522
                 const RefPtr<Context>& /*cr*/,
Packit 908522
                 TextExtents& /*metrics*/)
Packit 908522
    { ++count_render_glyph; return CAIRO_STATUS_SUCCESS; }
Packit 908522
Packit 908522
  int count_render_glyph;
Packit 908522
Packit 908522
protected:
Packit 908522
  NullRenderUserFont() : UserFontFace(), count_render_glyph(0) {}
Packit 908522
};
Packit 908522
Packit 908522
/******************************
Packit 908522
 * test_implement_text
Packit 908522
 ******************************/
Packit 908522
class ImplTextUserFont: public NullRenderUserFont
Packit 908522
{
Packit 908522
public:
Packit 908522
  static RefPtr<ImplTextUserFont> create() { return RefPtr<ImplTextUserFont>(new ImplTextUserFont());};
Packit 908522
  ErrorStatus text_to_glyphs(const RefPtr<ScaledFont>& /*scaled_font*/,
Packit 908522
                                     const std::string& /*utf8*/,
Packit 908522
                                     std::vector<Glyph>& glyphs,
Packit 908522
                                     std::vector<TextCluster>& /*clusters*/,
Packit 908522
                                     TextClusterFlags& /*cluster_flags*/) override
Packit 908522
  {
Packit 908522
    ++count_text_to_glyphs;
Packit 908522
    // return an arbitrary glyph
Packit 908522
    Glyph g = {84, 0, 0};
Packit 908522
    glyphs.push_back(g);
Packit 908522
    return CAIRO_STATUS_SUCCESS;
Packit 908522
  }
Packit 908522
  int count_text_to_glyphs;
Packit 908522
Packit 908522
protected:
Packit 908522
  ImplTextUserFont() : count_text_to_glyphs(0) {}
Packit 908522
};
Packit 908522
Packit 908522
void test_implement_text()
Packit 908522
{
Packit 908522
  TestSetup setup;
Packit 908522
  auto font = ImplTextUserFont::create();
Packit 908522
  setup.cr->set_font_face(font);
Packit 908522
  setup.cr->show_text("hello");
Packit 908522
  BOOST_REQUIRE(font->count_text_to_glyphs > 0);
Packit 908522
  BOOST_REQUIRE(font->count_render_glyph > 0);
Packit 908522
}
Packit 908522
Packit 908522
/******************************
Packit 908522
 * test_implement_unicode
Packit 908522
 ******************************/
Packit 908522
class ImplUnicodeUserFont: public NullRenderUserFont
Packit 908522
{
Packit 908522
public:
Packit 908522
  static RefPtr<ImplUnicodeUserFont> create() { return RefPtr<ImplUnicodeUserFont>(new ImplUnicodeUserFont());};
Packit 908522
  ErrorStatus unicode_to_glyph(const RefPtr<ScaledFont>& /*scaled_font*/,
Packit 908522
                                       unsigned long /*unicode*/,
Packit 908522
                                       unsigned long& /*glyph*/) override
Packit 908522
  { ++count_unicode_to_glyph;  return CAIRO_STATUS_SUCCESS;}
Packit 908522
  int count_unicode_to_glyph;
Packit 908522
Packit 908522
protected:
Packit 908522
  ImplUnicodeUserFont() : NullRenderUserFont(), count_unicode_to_glyph(0) {}
Packit 908522
};
Packit 908522
Packit 908522
void test_implement_unicode()
Packit 908522
{
Packit 908522
  TestSetup setup;
Packit 908522
  auto font = ImplTextUserFont::create();
Packit 908522
  setup.cr->set_font_face(font);
Packit 908522
  setup.cr->show_text("hello");
Packit 908522
  BOOST_REQUIRE(font->count_text_to_glyphs > 0);
Packit 908522
  BOOST_REQUIRE(font->count_render_glyph > 0);
Packit 908522
}
Packit 908522
Packit 908522
/******************************
Packit 908522
 * test_implement_both
Packit 908522
 ******************************/
Packit 908522
class ImplBothUserFont: public NullRenderUserFont
Packit 908522
{
Packit 908522
public:
Packit 908522
  static RefPtr<ImplBothUserFont> create() { return RefPtr<ImplBothUserFont>(new ImplBothUserFont());};
Packit 908522
  ErrorStatus unicode_to_glyph(const RefPtr<ScaledFont>& /*scaled_font*/,
Packit 908522
                                       unsigned long /*unicode*/,
Packit 908522
                                       unsigned long& /*glyph*/) override
Packit 908522
  { ++count_unicode_to_glyph;  return CAIRO_STATUS_SUCCESS;}
Packit 908522
  int count_unicode_to_glyph;
Packit 908522
Packit 908522
  ErrorStatus text_to_glyphs(const RefPtr<ScaledFont>& /*scaled_font*/,
Packit 908522
                                     const std::string& /*utf8*/,
Packit 908522
                                     std::vector<Glyph>& glyphs,
Packit 908522
                                     std::vector<TextCluster>& /*clusters*/,
Packit 908522
                                     TextClusterFlags& /*cluster_flags*/) override
Packit 908522
  {
Packit 908522
    ++count_text_to_glyphs;
Packit 908522
    // return an arbitrary glyph
Packit 908522
    Glyph g = {84, 0, 0};
Packit 908522
    glyphs.push_back(g);
Packit 908522
    return CAIRO_STATUS_SUCCESS;
Packit 908522
  }
Packit 908522
  int count_text_to_glyphs;
Packit 908522
Packit 908522
protected:
Packit 908522
  ImplBothUserFont() : NullRenderUserFont(), count_unicode_to_glyph(0),
Packit 908522
  count_text_to_glyphs(0) {}
Packit 908522
};
Packit 908522
Packit 908522
void test_implement_both()
Packit 908522
{
Packit 908522
  TestSetup setup;
Packit 908522
  auto font = ImplBothUserFont::create();
Packit 908522
  setup.cr->set_font_face(font);
Packit 908522
  setup.cr->show_text("hello");
Packit 908522
  // text_to_glyphs should take precedence
Packit 908522
  BOOST_REQUIRE(font->count_text_to_glyphs > 0);
Packit 908522
  BOOST_REQUIRE(font->count_unicode_to_glyph == 0);
Packit 908522
  BOOST_REQUIRE(font->count_render_glyph > 0);
Packit 908522
}
Packit 908522
Packit 908522
/******************************
Packit 908522
 * test_implement_neither
Packit 908522
 ******************************/
Packit 908522
class ImplNeitherUserFont: public NullRenderUserFont
Packit 908522
{
Packit 908522
public:
Packit 908522
  static RefPtr<ImplNeitherUserFont> create() { return RefPtr<ImplNeitherUserFont>(new ImplNeitherUserFont());};
Packit 908522
Packit 908522
protected:
Packit 908522
  ImplNeitherUserFont() : NullRenderUserFont() {}
Packit 908522
};
Packit 908522
Packit 908522
void test_implement_neither()
Packit 908522
{
Packit 908522
  TestSetup setup;
Packit 908522
  auto font = ImplNeitherUserFont::create();
Packit 908522
  setup.cr->set_font_face(font);
Packit 908522
  setup.cr->show_text("hello");
Packit 908522
  BOOST_REQUIRE(font->count_render_glyph > 0);
Packit 908522
}
Packit 908522
Packit 908522
/******************************
Packit 908522
 * test_implement_init
Packit 908522
 ******************************/
Packit 908522
class ImplInitUserFont: public NullRenderUserFont
Packit 908522
{
Packit 908522
public:
Packit 908522
  static RefPtr<ImplInitUserFont> create() { return RefPtr<ImplInitUserFont>(new ImplInitUserFont());};
Packit 908522
  ErrorStatus init(const RefPtr<ScaledFont>& /*scaled_font*/,
Packit 908522
                           const RefPtr<Context>& /*cr*/,
Packit 908522
                           FontExtents& /*extents*/) override
Packit 908522
  {++count_init; return CAIRO_STATUS_SUCCESS;}
Packit 908522
Packit 908522
  int count_init;
Packit 908522
Packit 908522
protected:
Packit 908522
  ImplInitUserFont() : NullRenderUserFont(), count_init(0) {}
Packit 908522
};
Packit 908522
Packit 908522
void test_implement_init()
Packit 908522
{
Packit 908522
  TestSetup setup;
Packit 908522
  auto font = ImplInitUserFont::create();
Packit 908522
  setup.cr->set_font_face(font);
Packit 908522
  setup.cr->show_text("hello");
Packit 908522
  BOOST_REQUIRE(font->count_init > 0);
Packit 908522
  BOOST_REQUIRE(font->count_render_glyph > 0);
Packit 908522
}
Packit 908522
Packit 908522
class ExceptionUserFont : public UserFontFace
Packit 908522
{
Packit 908522
public:
Packit 908522
  static RefPtr<ExceptionUserFont> create(int flags) { return RefPtr<ExceptionUserFont>(new ExceptionUserFont(flags));};
Packit 908522
Packit 908522
  ErrorStatus
Packit 908522
  render_glyph(const RefPtr<ScaledFont>& /*scaled_font*/,
Packit 908522
               unsigned long /*glyph*/,
Packit 908522
               const RefPtr<Context>& /*cr*/,
Packit 908522
               TextExtents& /*metrics*/)
Packit 908522
  {
Packit 908522
    count_render_glyph++;
Packit 908522
    if (m_flags & FLAG_RENDER)
Packit 908522
      throw std::logic_error("render-glyph exception");
Packit 908522
    return CAIRO_STATUS_SUCCESS;
Packit 908522
  }
Packit 908522
Packit 908522
  ErrorStatus
Packit 908522
  unicode_to_glyph(const RefPtr<ScaledFont>& /*scaled_font*/,
Packit 908522
                                       unsigned long unicode,
Packit 908522
                                       unsigned long& glyph)
Packit 908522
  {
Packit 908522
    count_unicode_to_glyph++;
Packit 908522
    if (m_flags & FLAG_UNICODE)
Packit 908522
      throw std::logic_error("unicode-to-glyph exception");
Packit 908522
Packit 908522
    glyph = unicode;
Packit 908522
    return CAIRO_STATUS_SUCCESS;
Packit 908522
  }
Packit 908522
Packit 908522
  ErrorStatus
Packit 908522
  init(const RefPtr<ScaledFont>& /*scaled_font*/,
Packit 908522
                         const RefPtr<Context>& /*cr*/,
Packit 908522
                         FontExtents& /*extents*/) override
Packit 908522
  {
Packit 908522
    count_init++;
Packit 908522
    if (m_flags & FLAG_INIT)
Packit 908522
      throw std::logic_error("init exception");
Packit 908522
    return CAIRO_STATUS_SUCCESS;
Packit 908522
  }
Packit 908522
Packit 908522
  int count_render_glyph;
Packit 908522
  int count_text_to_glyphs;
Packit 908522
  int count_unicode_to_glyph;
Packit 908522
  int count_init;
Packit 908522
  int m_flags;
Packit 908522
Packit 908522
  static const int FLAG_INIT = 1 << 0;
Packit 908522
  static const int FLAG_UNICODE = 1 << 1;
Packit 908522
  static const int FLAG_RENDER = 1 << 2;
Packit 908522
Packit 908522
protected:
Packit 908522
  ExceptionUserFont(int flags) : UserFontFace(), count_render_glyph(0),
Packit 908522
  count_text_to_glyphs(0), count_unicode_to_glyph(0), count_init(0),
Packit 908522
  m_flags(flags) {}
Packit 908522
};
Packit 908522
Packit 908522
void test_user_font_exception()
Packit 908522
{
Packit 908522
  auto font =
Packit 908522
    ExceptionUserFont::create(ExceptionUserFont::FLAG_INIT);
Packit 908522
  BOOST_CHECK(font);
Packit 908522
Packit 908522
  // the init() callback will throw an exception, if this isn't handled in the
Packit 908522
  // callback wrapper, the program will abort since an exception can't unwind
Packit 908522
  // through C code.  However, due to the exception being thrown, the create()
Packit 908522
  // function will fail and throw a new exception.  So if the executable doesn't
Packit 908522
  // abort, we should get an exception here.
Packit 908522
  Cairo::RefPtr<Cairo::ScaledFont> scaled_font;
Packit 908522
  BOOST_CHECK_THROW (scaled_font = Cairo::ScaledFont::create(font,
Packit 908522
                                                             Cairo::scaling_matrix(10, 10),
Packit 908522
                                                             Cairo::identity_matrix(),
Packit 908522
                                                             Cairo::FontOptions()),
Packit 908522
                     Cairo::logic_error);
Packit 908522
  BOOST_CHECK (font->count_init > 0);
Packit 908522
Packit 908522
  // now test when an exception is thrown in unicode_to_glyph
Packit 908522
  font = ExceptionUserFont::create(ExceptionUserFont::FLAG_UNICODE);
Packit 908522
  BOOST_CHECK_NO_THROW (scaled_font = Cairo::ScaledFont::create(font,
Packit 908522
                                                                Cairo::scaling_matrix(10, 10),
Packit 908522
                                                                Cairo::identity_matrix(),
Packit 908522
                                                                Cairo::FontOptions()));
Packit 908522
  TestSetup setup;
Packit 908522
  setup.cr->set_font_face(font);
Packit 908522
  // this call should throw an exception since the callback wrapper will return
Packit 908522
  // an error status (that will be translated into an exception) but the test
Packit 908522
  // shouldn't abort since the callback exceptions are handled by the callback
Packit 908522
  // wrapper
Packit 908522
  BOOST_REQUIRE_EQUAL (CAIRO_STATUS_SUCCESS, font->get_status());
Packit 908522
  BOOST_CHECK_THROW(setup.cr->show_text("Hello, world"), Cairo::logic_error);
Packit 908522
  BOOST_CHECK(font->count_unicode_to_glyph > 0);
Packit 908522
  BOOST_CHECK_EQUAL(font->count_render_glyph, 0);
Packit 908522
Packit 908522
  // now test when an exception is thrown in render_glyph
Packit 908522
  font = ExceptionUserFont::create(ExceptionUserFont::FLAG_RENDER);
Packit 908522
  BOOST_CHECK_NO_THROW (scaled_font = Cairo::ScaledFont::create(font,
Packit 908522
                                                                Cairo::scaling_matrix(10, 10),
Packit 908522
                                                                Cairo::identity_matrix(),
Packit 908522
                                                                Cairo::FontOptions()));
Packit 908522
  // need a new setup since the old cr is now in an error state, so attemtping
Packit 908522
  // to use it will throw an exception
Packit 908522
  TestSetup setup2;
Packit 908522
  BOOST_CHECK_NO_THROW(setup2.cr->set_font_face(font));
Packit 908522
  BOOST_REQUIRE_EQUAL (CAIRO_STATUS_SUCCESS, font->get_status());
Packit 908522
  BOOST_CHECK_THROW(setup2.cr->show_text("Hello, world"), Cairo::logic_error);
Packit 908522
  BOOST_CHECK (font->count_unicode_to_glyph > 0);
Packit 908522
  BOOST_CHECK (font->count_render_glyph > 0);
Packit 908522
}
Packit 908522
Packit 908522
Packit 908522
test_suite*
Packit 908522
init_unit_test_suite(int argc, char* argv[])
Packit 908522
{
Packit 908522
  // compile even with -Werror
Packit 908522
  if (argc && argv) {}
Packit 908522
Packit 908522
  test_suite* test= BOOST_TEST_SUITE( "Cairo::UserFontFace Tests" );
Packit 908522
Packit 908522
  test->add (BOOST_TEST_CASE (&test_implement_text));
Packit 908522
  test->add (BOOST_TEST_CASE (&test_implement_unicode));
Packit 908522
  test->add (BOOST_TEST_CASE (&test_implement_both));
Packit 908522
  test->add (BOOST_TEST_CASE (&test_implement_neither));
Packit 908522
  test->add (BOOST_TEST_CASE (&test_implement_init));
Packit 908522
  test->add (BOOST_TEST_CASE (&test_user_font_exception));
Packit 908522
Packit 908522
  return test;
Packit 908522
}