13
0
livetrax/libs/cairomm/cairomm/context.cc
Hans Baier 636f2184a5 * applied patch for ardour-3.0 to compile on OS X thanks to Sakari Bergen
git-svn-id: svn://localhost/ardour2/branches/3.0@3338 d708f5d6-7413-0410-9779-e7cbd77b26cf
2008-05-12 11:46:53 +00:00

798 lines
22 KiB
C++

/* Copyright (C) 2005 The cairomm Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <cairomm/context.h>
#include <cairomm/context_private.h>
#include <cairomm/private.h>
#include <cairomm/surface.h>
/* M_PI is defined in math.h in the case of Microsoft Visual C++ */
#if defined(_MSC_VER)
#define _USE_MATH_DEFINES
#include <math.h>
#endif
using namespace Cairo::Private;
namespace Cairo
{
Context::Context(const RefPtr<Surface>& target)
: m_cobject(0)
{
m_cobject = cairo_create(target->cobj());
check_object_status_and_throw_exception(*this);
}
RefPtr<Context> Context::create(const RefPtr<Surface>& target)
{
return RefPtr<Context>(new Context(target));
}
Context::Context(cairo_t* cobject, bool has_reference)
: m_cobject(0)
{
if(has_reference)
m_cobject = cobject;
else
m_cobject = cairo_reference(cobject);
}
Context::~Context()
{
if(m_cobject)
cairo_destroy(m_cobject);
}
void Context::reference() const
{
cairo_reference(m_cobject);
}
void Context::unreference() const
{
cairo_destroy(m_cobject);
}
void Context::save()
{
cairo_save(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::restore()
{
cairo_restore(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::set_operator(Operator op)
{
cairo_set_operator(m_cobject, static_cast<cairo_operator_t>(op));
check_object_status_and_throw_exception(*this);
}
void Context::set_source(const RefPtr<const Pattern>& source)
{
cairo_set_source(m_cobject, const_cast<cairo_pattern_t*>(source->cobj()));
check_object_status_and_throw_exception(*this);
}
void Context::set_source_rgb(double red, double green, double blue)
{
cairo_set_source_rgb(m_cobject, red, green, blue);
check_object_status_and_throw_exception(*this);
}
void Context::set_source_rgba(double red, double green, double blue,
double alpha)
{
cairo_set_source_rgba(m_cobject, red, green, blue, alpha);
check_object_status_and_throw_exception(*this);
}
void Context::set_source(const RefPtr<Surface>& surface, double x, double y)
{
cairo_set_source_surface(m_cobject, surface->cobj(), x, y);
check_object_status_and_throw_exception(*this);
}
void Context::set_tolerance(double tolerance)
{
cairo_set_tolerance(m_cobject, tolerance);
check_object_status_and_throw_exception(*this);
}
void Context::set_antialias(Antialias antialias)
{
cairo_set_antialias(m_cobject, static_cast<cairo_antialias_t>(antialias));
check_object_status_and_throw_exception(*this);
}
void Context::set_fill_rule(FillRule fill_rule)
{
cairo_set_fill_rule(m_cobject, static_cast<cairo_fill_rule_t>(fill_rule));
check_object_status_and_throw_exception(*this);
}
void Context::set_line_width(double width)
{
cairo_set_line_width(m_cobject, width);
check_object_status_and_throw_exception(*this);
}
void Context::set_line_cap(LineCap line_cap)
{
cairo_set_line_cap(m_cobject, static_cast<cairo_line_cap_t>(line_cap));
check_object_status_and_throw_exception(*this);
}
void Context::set_line_join(LineJoin line_join)
{
cairo_set_line_join(m_cobject, static_cast<cairo_line_join_t>(line_join));
check_object_status_and_throw_exception(*this);
}
void Context::set_dash(std::valarray<double>& dashes, double offset)
{
cairo_set_dash(m_cobject, &dashes[0], dashes.size(), offset);
check_object_status_and_throw_exception(*this);
}
void Context::set_dash(std::vector<double>& dashes, double offset)
{
cairo_set_dash(m_cobject, &dashes[0], dashes.size(), offset);
check_object_status_and_throw_exception(*this);
}
void Context::unset_dash()
{
cairo_set_dash(m_cobject, NULL, 0, 0.0);
check_object_status_and_throw_exception(*this);
}
void Context::set_miter_limit(double limit)
{
cairo_set_miter_limit(m_cobject, limit);
check_object_status_and_throw_exception(*this);
}
void Context::translate(double tx, double ty)
{
cairo_translate(m_cobject, tx, ty);
check_object_status_and_throw_exception(*this);
}
void Context::scale(double sx, double sy)
{
cairo_scale(m_cobject, sx, sy);
check_object_status_and_throw_exception(*this);
}
void Context::rotate(double angle_radians)
{
cairo_rotate(m_cobject, angle_radians);
check_object_status_and_throw_exception(*this);
}
void Context::rotate_degrees(double angle_degrees)
{
cairo_rotate(m_cobject, angle_degrees * M_PI/180.0);
check_object_status_and_throw_exception(*this);
}
void Context::transform(const Matrix& matrix)
{
cairo_transform(m_cobject, &matrix);
check_object_status_and_throw_exception(*this);
}
void Context::set_matrix(const Matrix& matrix)
{
cairo_set_matrix(m_cobject, &matrix);
check_object_status_and_throw_exception(*this);
}
void Context::set_identity_matrix()
{
cairo_identity_matrix(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::user_to_device(double& x, double& y)
{
cairo_user_to_device(m_cobject, &x, &y);
check_object_status_and_throw_exception(*this);
}
void Context::user_to_device_distance(double& dx, double& dy)
{
cairo_user_to_device_distance(m_cobject, &dx, &dy);
check_object_status_and_throw_exception(*this);
}
void Context::device_to_user(double& x, double& y)
{
cairo_device_to_user(m_cobject, &x, &y);
check_object_status_and_throw_exception(*this);
}
void Context::device_to_user_distance(double& dx, double& dy)
{
cairo_device_to_user_distance(m_cobject, &dx, &dy);
check_object_status_and_throw_exception(*this);
}
void Context::begin_new_path()
{
cairo_new_path(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::begin_new_sub_path()
{
cairo_new_sub_path(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::move_to(double x, double y)
{
cairo_move_to(m_cobject, x, y);
check_object_status_and_throw_exception(*this);
}
void Context::line_to(double x, double y)
{
cairo_line_to(m_cobject, x, y);
check_object_status_and_throw_exception(*this);
}
void Context::curve_to(double x1, double y1, double x2, double y2, double x3, double y3)
{
cairo_curve_to(m_cobject, x1, y1, x2, y2, x3, y3);
check_object_status_and_throw_exception(*this);
}
void Context::arc(double xc, double yc, double radius, double angle1, double angle2)
{
cairo_arc(m_cobject, xc, yc, radius, angle1, angle2);
check_object_status_and_throw_exception(*this);
}
void Context::arc_negative(double xc, double yc, double radius, double angle1, double angle2)
{
cairo_arc_negative(m_cobject, xc, yc, radius, angle1, angle2);
check_object_status_and_throw_exception(*this);
}
void Context::rel_move_to(double dx, double dy)
{
cairo_rel_move_to(m_cobject, dx, dy);
check_object_status_and_throw_exception(*this);
}
void Context::rel_line_to(double dx, double dy)
{
cairo_rel_line_to(m_cobject, dx, dy);
check_object_status_and_throw_exception(*this);
}
void Context::rel_curve_to(double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
{
cairo_rel_curve_to(m_cobject, dx1, dy1, dx2, dy2, dx3, dy3);
check_object_status_and_throw_exception(*this);
}
void Context::rectangle(double x, double y, double width, double height)
{
cairo_rectangle(m_cobject, x, y, width, height);
check_object_status_and_throw_exception(*this);
}
void Context::close_path()
{
cairo_close_path(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::paint()
{
cairo_paint(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::paint_with_alpha(double alpha)
{
cairo_paint_with_alpha(m_cobject, alpha);
check_object_status_and_throw_exception(*this);
}
void Context::mask(const RefPtr<const Pattern>& pattern)
{
cairo_mask(m_cobject, const_cast<cairo_pattern_t*>(pattern->cobj()));
check_object_status_and_throw_exception(*this);
}
void Context::mask(const RefPtr<const Surface>& surface, double surface_x, double surface_y)
{
cairo_mask_surface(m_cobject, const_cast<cairo_surface_t*>(surface->cobj()), surface_x, surface_y);
check_object_status_and_throw_exception(*this);
}
void Context::stroke()
{
cairo_stroke(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::stroke_preserve()
{
cairo_stroke_preserve(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::fill()
{
cairo_fill(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::fill_preserve()
{
cairo_fill_preserve(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::copy_page()
{
cairo_copy_page(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::show_page()
{
cairo_show_page(m_cobject);
check_object_status_and_throw_exception(*this);
}
bool Context::in_stroke(double x, double y) const
{
const bool result = cairo_in_stroke(m_cobject, x, y);
check_object_status_and_throw_exception(*this);
return result;
}
bool Context::in_fill(double x, double y) const
{
const bool result = cairo_in_fill(m_cobject, x, y);
check_object_status_and_throw_exception(*this);
return result;
}
void Context::get_stroke_extents(double& x1, double& y1, double& x2, double& y2) const
{
cairo_stroke_extents(m_cobject, &x1, &y1, &x2, &y2);
check_object_status_and_throw_exception(*this);
}
void Context::get_fill_extents(double& x1, double& y1, double& x2, double& y2) const
{
cairo_fill_extents(m_cobject, &x1, &y1, &x2, &y2);
check_object_status_and_throw_exception(*this);
}
void Context::reset_clip()
{
cairo_reset_clip(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::clip()
{
cairo_clip(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::clip_preserve()
{
cairo_clip_preserve(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::get_clip_extents(double& x1, double& y1, double& x2, double& y2) const
{
cairo_clip_extents(const_cast<cairo_t*>(m_cobject), &x1, &y1, &x2, &y2);
check_object_status_and_throw_exception(*this);
}
void Context::copy_clip_rectangle_list(std::vector<Rectangle>& rectangles) const
{
cairo_rectangle_list_t* c_list = 0;
// It would be nice if the cairo interface didn't copy it into a C array first
// and just let us do the copying...
c_list = cairo_copy_clip_rectangle_list(const_cast<cairo_t*>(m_cobject));
// the rectangle list contains a status field that we need to check and the
// cairo context also has a status that we need to check
// FIXME: do we want to throw an exception if the clip can't be represented by
// rectangles? or do we just want to return an empty list?
check_status_and_throw_exception(c_list->status);
check_object_status_and_throw_exception(*this);
// copy the C array into the passed C++ list
rectangles.assign(c_list->rectangles,
c_list->rectangles + c_list->num_rectangles);
// free the memory allocated to the C array since we've copied it into a
// standard C++ container
cairo_rectangle_list_destroy(c_list);
}
void Context::select_font_face(const std::string& family, FontSlant slant, FontWeight weight)
{
cairo_select_font_face(m_cobject, family.c_str(),
static_cast<cairo_font_slant_t>(slant),
static_cast<cairo_font_weight_t>(weight));
check_object_status_and_throw_exception(*this);
}
void Context::set_font_size(double size)
{
cairo_set_font_size(m_cobject, size);
check_object_status_and_throw_exception(*this);
}
void Context::set_font_matrix(const Matrix& matrix)
{
cairo_set_font_matrix(m_cobject, &matrix);
check_object_status_and_throw_exception(*this);
}
void Context::get_font_matrix(Matrix& matrix) const
{
cairo_get_font_matrix(m_cobject, &matrix);
check_object_status_and_throw_exception(*this);
}
void Context::set_font_options(const FontOptions& options)
{
cairo_set_font_options(m_cobject, options.cobj());
check_object_status_and_throw_exception(*this);
}
void Context::show_text(const std::string& utf8)
{
cairo_show_text(m_cobject, utf8.c_str());
check_object_status_and_throw_exception(*this);
}
void Context::show_glyphs(const std::vector<Glyph>& glyphs)
{
cairo_show_glyphs(m_cobject, const_cast<cairo_glyph_t*>(&glyphs[0]), glyphs.size());
check_object_status_and_throw_exception(*this);
}
RefPtr<FontFace> Context::get_font_face()
{
cairo_font_face_t* cfontface = cairo_get_font_face(m_cobject);
check_object_status_and_throw_exception(*this);
return RefPtr<FontFace>(new FontFace(cfontface, false /* does not have reference */));
}
RefPtr<const FontFace> Context::get_font_face() const
{
cairo_font_face_t* cfontface = cairo_get_font_face(m_cobject);
check_object_status_and_throw_exception(*this);
return RefPtr<const FontFace>(new FontFace(cfontface, false /* does not have reference */));
}
void Context::get_font_extents(FontExtents& extents) const
{
cairo_font_extents(m_cobject, &extents);
check_object_status_and_throw_exception(*this);
}
void Context::set_font_face(const RefPtr<const FontFace>& font_face)
{
cairo_set_font_face(m_cobject, const_cast<cairo_font_face_t*>(font_face->cobj()));
check_object_status_and_throw_exception(*this);
}
void Context::get_text_extents(const std::string& utf8, TextExtents& extents) const
{
cairo_text_extents(m_cobject, utf8.c_str(), &extents);
check_object_status_and_throw_exception(*this);
}
void Context::get_glyph_extents(const std::vector<Glyph>& glyphs, TextExtents& extents) const
{
cairo_glyph_extents(m_cobject, const_cast<cairo_glyph_t*>(&glyphs[0]), glyphs.size(), &extents);
check_object_status_and_throw_exception(*this);
}
void Context::text_path(const std::string& utf8)
{
cairo_text_path(m_cobject, utf8.c_str());
check_object_status_and_throw_exception(*this);
}
void Context::glyph_path(const std::vector<Glyph>& glyphs)
{
cairo_glyph_path(m_cobject, const_cast<cairo_glyph_t*>(&glyphs[0]), glyphs.size());
check_object_status_and_throw_exception(*this);
}
Operator Context::get_operator() const
{
const Operator result = static_cast<Operator>(cairo_get_operator(m_cobject));
check_object_status_and_throw_exception(*this);
return result;
}
static RefPtr<Pattern> get_pattern_wrapper (cairo_pattern_t* pattern)
{
cairo_pattern_type_t pattern_type = cairo_pattern_get_type (pattern);
switch (pattern_type)
{
case CAIRO_PATTERN_TYPE_SOLID:
return RefPtr<SolidPattern>(new SolidPattern(pattern, false /* does not have reference */));
break;
case CAIRO_PATTERN_TYPE_SURFACE:
return RefPtr<SurfacePattern>(new SurfacePattern(pattern, false /* does not have reference */));
break;
case CAIRO_PATTERN_TYPE_LINEAR:
return RefPtr<LinearGradient>(new LinearGradient(pattern, false /* does not have reference */));
break;
case CAIRO_PATTERN_TYPE_RADIAL:
return RefPtr<RadialGradient>(new RadialGradient(pattern, false /* does not have reference */));
break;
default:
return RefPtr<Pattern>(new Pattern(pattern, false /* does not have reference */));
}
}
RefPtr<Pattern> Context::get_source()
{
cairo_pattern_t* pattern = cairo_get_source(m_cobject);
check_object_status_and_throw_exception(*this);
return get_pattern_wrapper (pattern);
}
RefPtr<const Pattern> Context::get_source() const
{
cairo_pattern_t* pattern = cairo_get_source(m_cobject);
check_object_status_and_throw_exception(*this);
return RefPtr<const Pattern>::cast_const (get_pattern_wrapper (pattern));
}
double Context::get_tolerance() const
{
const double result = cairo_get_tolerance(m_cobject);
check_object_status_and_throw_exception(*this);
return result;
}
Antialias Context::get_antialias() const
{
const Antialias result = static_cast<Antialias>(cairo_get_antialias(m_cobject));
check_object_status_and_throw_exception(*this);
return result;
}
void Context::get_current_point(double& x, double& y) const
{
cairo_get_current_point(m_cobject, &x, &y);
check_object_status_and_throw_exception(*this);
}
FillRule Context::get_fill_rule() const
{
const FillRule result = static_cast<FillRule>(cairo_get_fill_rule(m_cobject));
check_object_status_and_throw_exception(*this);
return result;
}
double Context::get_line_width() const
{
const double result = cairo_get_line_width(m_cobject);
check_object_status_and_throw_exception(*this);
return result;
}
LineCap Context::get_line_cap() const
{
const LineCap result = static_cast<LineCap>(cairo_get_line_cap(m_cobject));
check_object_status_and_throw_exception(*this);
return result;
}
LineJoin Context::get_line_join() const
{
const LineJoin result = static_cast<LineJoin>(cairo_get_line_join(m_cobject));
check_object_status_and_throw_exception(*this);
return result;
}
double Context::get_miter_limit() const
{
const double result = cairo_get_miter_limit(m_cobject);
check_object_status_and_throw_exception(*this);
return result;
}
void
Context::get_dash(std::vector<double>& dashes, double& offset) const
{
// Allocate this array dynamically because some compilers complain about
// allocating arrays on the stack when the array size isn't a compile-time
// constant...
const int cnt = cairo_get_dash_count(m_cobject);
double* dash_array = new double[cnt];
cairo_get_dash(const_cast<cairo_t*>(m_cobject), dash_array, &offset);
check_object_status_and_throw_exception(*this);
dashes.assign(dash_array, dash_array + cnt);
delete[] dash_array;
}
void Context::get_matrix(Matrix& matrix)
{
cairo_get_matrix(m_cobject, &matrix);
check_object_status_and_throw_exception(*this);
}
static
RefPtr<Surface> get_surface_wrapper (cairo_surface_t* surface)
{
cairo_surface_type_t surface_type = cairo_surface_get_type (surface);
switch (surface_type)
{
case CAIRO_SURFACE_TYPE_IMAGE:
return RefPtr<ImageSurface>(new ImageSurface(surface, false /* does not have reference */));
break;
#if CAIRO_HAS_PDF_SURFACE
case CAIRO_SURFACE_TYPE_PDF:
return RefPtr<PdfSurface>(new PdfSurface(surface, false /* does not have reference */));
break;
#endif
#if CAIRO_HAS_PS_SURFACE
case CAIRO_SURFACE_TYPE_PS:
return RefPtr<PsSurface>(new PsSurface(surface, false /* does not have reference */));
break;
#endif
#if CAIRO_HAS_XLIB_SURFACE
case CAIRO_SURFACE_TYPE_XLIB:
return wrap_surface_xlib(surface);
break;
#endif
#if CAIRO_HAS_GLITZ_SURFACE
case CAIRO_SURFACE_TYPE_GLITZ:
return RefPtr<GlitzSurface>(new GlitzSurface(surface, false /* does not have reference */));
break;
#endif
#if CAIRO_HAS_QUARTZ_SURFACE
case CAIRO_SURFACE_TYPE_QUARTZ:
return wrap_surface_quartz(surface);
break;
#endif
#if CAIRO_HAS_WIN32_SURFACE
case CAIRO_SURFACE_TYPE_WIN32:
return wrap_surface_win32(surface);
break;
#endif
#if CAIRO_HAS_SVG_SURFACE
case CAIRO_SURFACE_TYPE_SVG:
return RefPtr<SvgSurface>(new SvgSurface(surface, false /* does not have reference */));
break;
#endif
// the following surfaces are not directly supported in cairomm yet
case CAIRO_SURFACE_TYPE_DIRECTFB:
case CAIRO_SURFACE_TYPE_OS2:
case CAIRO_SURFACE_TYPE_BEOS:
case CAIRO_SURFACE_TYPE_XCB:
default:
return RefPtr<Surface>(new Surface(surface, false /* does not have reference */));
}
}
RefPtr<Surface> Context::get_target()
{
cairo_surface_t* surface = cairo_get_target(const_cast<cairo_t*>(m_cobject));
check_object_status_and_throw_exception(*this);
return get_surface_wrapper (surface);
}
RefPtr<const Surface> Context::get_target() const
{
cairo_surface_t* surface = cairo_get_target(const_cast<cairo_t*>(m_cobject));
check_object_status_and_throw_exception(*this);
return RefPtr<const Surface>::cast_const (get_surface_wrapper (surface));
}
Path* Context::copy_path() const
{
cairo_path_t* cresult = cairo_copy_path(const_cast<cairo_t*>(m_cobject));
check_object_status_and_throw_exception(*this);
return new Path(cresult, true /* take ownership */); //The caller must delete it.
}
Path* Context::copy_path_flat() const
{
cairo_path_t* cresult = cairo_copy_path_flat(const_cast<cairo_t*>(m_cobject));
check_object_status_and_throw_exception(*this);
return new Path(cresult, true /* take ownership */); //The caller must delete it.
}
void Context::append_path(const Path& path)
{
cairo_append_path(m_cobject, const_cast<cairo_path_t*>(path.cobj()));
check_object_status_and_throw_exception(*this);
}
void Context::push_group()
{
cairo_push_group(m_cobject);
check_object_status_and_throw_exception(*this);
}
void Context::push_group_with_content(Content content)
{
cairo_push_group_with_content(m_cobject, static_cast<cairo_content_t>(content));
check_object_status_and_throw_exception(*this);
}
RefPtr<Pattern> Context::pop_group()
{
cairo_pattern_t* pattern = cairo_pop_group(m_cobject);
check_object_status_and_throw_exception(*this);
return get_pattern_wrapper(pattern);
}
void Context::pop_group_to_source()
{
cairo_pop_group_to_source(m_cobject);
check_object_status_and_throw_exception(*this);
}
RefPtr<Surface> Context::get_group_target()
{
cairo_surface_t* surface = cairo_get_group_target(m_cobject);
// surface can be NULL if you're not between push/pop group calls
if(!surface)
{
// FIXME: is this really the right way to handle this?
throw_exception(CAIRO_STATUS_NULL_POINTER);
}
return get_surface_wrapper(surface);
}
RefPtr<const Surface> Context::get_group_target() const
{
cairo_surface_t* surface = cairo_get_group_target(m_cobject);
// surface can be NULL if you're not between push/pop group calls
if(!surface)
{
// FIXME: is this really the right way to handle this?
throw_exception(CAIRO_STATUS_NULL_POINTER);
}
return get_surface_wrapper(surface);
}
} //namespace Cairo
// vim: ts=2 sw=2 et