1 /* Copyright (C) 2005 The cairomm Development Team
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Library General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Library General Public License for more details.
13 * You should have received a copy of the GNU Library General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 #include <cairomm/context.h>
20 #include <cairomm/private.h>
22 /* M_PI is defined in math.h in the case of Microsoft Visual C++ */
24 #define _USE_MATH_DEFINES
31 Context::Context(const RefPtr<Surface>& target)
34 m_cobject = cairo_create(target->cobj());
35 check_object_status_and_throw_exception(*this);
38 RefPtr<Context> Context::create(const RefPtr<Surface>& target)
40 return RefPtr<Context>(new Context(target));
43 Context::Context(cairo_t* cobject, bool has_reference)
49 m_cobject = cairo_reference(cobject);
55 cairo_destroy(m_cobject);
59 void Context::reference() const
61 cairo_reference(m_cobject);
64 void Context::unreference() const
66 cairo_destroy(m_cobject);
71 cairo_save(m_cobject);
72 check_object_status_and_throw_exception(*this);
75 void Context::restore()
77 cairo_restore(m_cobject);
78 check_object_status_and_throw_exception(*this);
81 void Context::set_operator(Operator op)
83 cairo_set_operator(m_cobject, static_cast<cairo_operator_t>(op));
84 check_object_status_and_throw_exception(*this);
87 void Context::set_source(const RefPtr<const Pattern>& source)
89 cairo_set_source(m_cobject, const_cast<cairo_pattern_t*>(source->cobj()));
90 check_object_status_and_throw_exception(*this);
93 void Context::set_source_rgb(double red, double green, double blue)
95 cairo_set_source_rgb(m_cobject, red, green, blue);
96 check_object_status_and_throw_exception(*this);
99 void Context::set_source_rgba(double red, double green, double blue,
102 cairo_set_source_rgba(m_cobject, red, green, blue, alpha);
103 check_object_status_and_throw_exception(*this);
106 void Context::set_source(const RefPtr<Surface>& surface, double x, double y)
108 cairo_set_source_surface(m_cobject, surface->cobj(), x, y);
109 check_object_status_and_throw_exception(*this);
112 void Context::set_tolerance(double tolerance)
114 cairo_set_tolerance(m_cobject, tolerance);
115 check_object_status_and_throw_exception(*this);
118 void Context::set_antialias(Antialias antialias)
120 cairo_set_antialias(m_cobject, static_cast<cairo_antialias_t>(antialias));
121 check_object_status_and_throw_exception(*this);
124 void Context::set_fill_rule(FillRule fill_rule)
126 cairo_set_fill_rule(m_cobject, static_cast<cairo_fill_rule_t>(fill_rule));
127 check_object_status_and_throw_exception(*this);
130 void Context::set_line_width(double width)
132 cairo_set_line_width(m_cobject, width);
133 check_object_status_and_throw_exception(*this);
136 void Context::set_line_cap(LineCap line_cap)
138 cairo_set_line_cap(m_cobject, static_cast<cairo_line_cap_t>(line_cap));
139 check_object_status_and_throw_exception(*this);
142 void Context::set_line_join(LineJoin line_join)
144 cairo_set_line_join(m_cobject, static_cast<cairo_line_join_t>(line_join));
145 check_object_status_and_throw_exception(*this);
148 void Context::set_dash(std::valarray<double>& dashes, double offset)
150 cairo_set_dash(m_cobject, &dashes[0], dashes.size(), offset);
151 check_object_status_and_throw_exception(*this);
154 void Context::unset_dash()
156 cairo_set_dash(m_cobject, NULL, 0, 0.0);
157 check_object_status_and_throw_exception(*this);
160 void Context::set_miter_limit(double limit)
162 cairo_set_miter_limit(m_cobject, limit);
163 check_object_status_and_throw_exception(*this);
166 void Context::translate(double tx, double ty)
168 cairo_translate(m_cobject, tx, ty);
169 check_object_status_and_throw_exception(*this);
172 void Context::scale(double sx, double sy)
174 cairo_scale(m_cobject, sx, sy);
175 check_object_status_and_throw_exception(*this);
178 void Context::rotate(double angle_radians)
180 cairo_rotate(m_cobject, angle_radians);
181 check_object_status_and_throw_exception(*this);
184 void Context::rotate_degrees(double angle_degrees)
186 cairo_rotate(m_cobject, angle_degrees * M_PI/180.0);
187 check_object_status_and_throw_exception(*this);
190 void Context::transform(const Matrix& matrix)
192 cairo_transform(m_cobject, &matrix);
193 check_object_status_and_throw_exception(*this);
196 void Context::set_matrix(const Matrix& matrix)
198 cairo_set_matrix(m_cobject, &matrix);
199 check_object_status_and_throw_exception(*this);
202 void Context::set_identity_matrix()
204 cairo_identity_matrix(m_cobject);
205 check_object_status_and_throw_exception(*this);
208 void Context::user_to_device(double& x, double& y)
210 cairo_user_to_device(m_cobject, &x, &y);
211 check_object_status_and_throw_exception(*this);
214 void Context::user_to_device_distance(double& dx, double& dy)
216 cairo_user_to_device_distance(m_cobject, &dx, &dy);
217 check_object_status_and_throw_exception(*this);
220 void Context::device_to_user(double& x, double& y)
222 cairo_device_to_user(m_cobject, &x, &y);
223 check_object_status_and_throw_exception(*this);
226 void Context::device_to_user_distance(double& dx, double& dy)
228 cairo_device_to_user_distance(m_cobject, &dx, &dy);
229 check_object_status_and_throw_exception(*this);
232 void Context::begin_new_path()
234 cairo_new_path(m_cobject);
235 check_object_status_and_throw_exception(*this);
238 void Context::begin_new_sub_path()
240 cairo_new_sub_path(m_cobject);
241 check_object_status_and_throw_exception(*this);
244 void Context::move_to(double x, double y)
246 cairo_move_to(m_cobject, x, y);
247 check_object_status_and_throw_exception(*this);
250 void Context::line_to(double x, double y)
252 cairo_line_to(m_cobject, x, y);
253 check_object_status_and_throw_exception(*this);
256 void Context::curve_to(double x1, double y1, double x2, double y2, double x3, double y3)
258 cairo_curve_to(m_cobject, x1, y1, x2, y2, x3, y3);
259 check_object_status_and_throw_exception(*this);
262 void Context::arc(double xc, double yc, double radius, double angle1, double angle2)
264 cairo_arc(m_cobject, xc, yc, radius, angle1, angle2);
265 check_object_status_and_throw_exception(*this);
268 void Context::arc_negative(double xc, double yc, double radius, double angle1, double angle2)
270 cairo_arc_negative(m_cobject, xc, yc, radius, angle1, angle2);
271 check_object_status_and_throw_exception(*this);
274 void Context::rel_move_to(double dx, double dy)
276 cairo_rel_move_to(m_cobject, dx, dy);
277 check_object_status_and_throw_exception(*this);
280 void Context::rel_line_to(double dx, double dy)
282 cairo_rel_line_to(m_cobject, dx, dy);
283 check_object_status_and_throw_exception(*this);
286 void Context::rel_curve_to(double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
288 cairo_rel_curve_to(m_cobject, dx1, dy1, dx2, dy2, dx3, dy3);
289 check_object_status_and_throw_exception(*this);
292 void Context::rectangle(double x, double y, double width, double height)
294 cairo_rectangle(m_cobject, x, y, width, height);
295 check_object_status_and_throw_exception(*this);
298 void Context::close_path()
300 cairo_close_path(m_cobject);
301 check_object_status_and_throw_exception(*this);
304 void Context::paint()
306 cairo_paint(m_cobject);
307 check_object_status_and_throw_exception(*this);
310 void Context::paint_with_alpha(double alpha)
312 cairo_paint_with_alpha(m_cobject, alpha);
313 check_object_status_and_throw_exception(*this);
316 void Context::mask(const RefPtr<const Pattern>& pattern)
318 cairo_mask(m_cobject, const_cast<cairo_pattern_t*>(pattern->cobj()));
319 check_object_status_and_throw_exception(*this);
322 void Context::mask(const RefPtr<const Surface>& surface, double surface_x, double surface_y)
324 cairo_mask_surface(m_cobject, const_cast<cairo_surface_t*>(surface->cobj()), surface_x, surface_y);
325 check_object_status_and_throw_exception(*this);
328 void Context::stroke()
330 cairo_stroke(m_cobject);
331 check_object_status_and_throw_exception(*this);
334 void Context::stroke_preserve()
336 cairo_stroke_preserve(m_cobject);
337 check_object_status_and_throw_exception(*this);
342 cairo_fill(m_cobject);
343 check_object_status_and_throw_exception(*this);
346 void Context::fill_preserve()
348 cairo_fill_preserve(m_cobject);
349 check_object_status_and_throw_exception(*this);
352 void Context::copy_page()
354 cairo_copy_page(m_cobject);
355 check_object_status_and_throw_exception(*this);
358 void Context::show_page()
360 cairo_show_page(m_cobject);
361 check_object_status_and_throw_exception(*this);
364 bool Context::in_stroke(double x, double y) const
366 const bool result = cairo_in_stroke(m_cobject, x, y);
367 check_object_status_and_throw_exception(*this);
371 bool Context::in_fill(double x, double y) const
373 const bool result = cairo_in_fill(m_cobject, x, y);
374 check_object_status_and_throw_exception(*this);
378 void Context::get_stroke_extents(double& x1, double& y1, double& x2, double& y2) const
380 cairo_stroke_extents(m_cobject, &x1, &y1, &x2, &y2);
381 check_object_status_and_throw_exception(*this);
384 void Context::get_fill_extents(double& x1, double& y1, double& x2, double& y2) const
386 cairo_fill_extents(m_cobject, &x1, &y1, &x2, &y2);
387 check_object_status_and_throw_exception(*this);
390 void Context::reset_clip()
392 cairo_reset_clip(m_cobject);
393 check_object_status_and_throw_exception(*this);
398 cairo_clip(m_cobject);
399 check_object_status_and_throw_exception(*this);
402 void Context::clip_preserve()
404 cairo_clip_preserve(m_cobject);
405 check_object_status_and_throw_exception(*this);
408 void Context::select_font_face(const std::string& family, FontSlant slant, FontWeight weight)
410 cairo_select_font_face (m_cobject, family.c_str(),
411 static_cast<cairo_font_slant_t>(slant),
412 static_cast<cairo_font_weight_t>(weight));
413 check_object_status_and_throw_exception(*this);
416 void Context::set_font_size(double size)
418 cairo_set_font_size(m_cobject, size);
419 check_object_status_and_throw_exception(*this);
422 void Context::set_font_matrix(const Matrix& matrix)
424 cairo_set_font_matrix(m_cobject, &matrix);
425 check_object_status_and_throw_exception(*this);
428 void Context::get_font_matrix(Matrix& matrix) const
430 cairo_get_font_matrix(m_cobject, &matrix);
431 check_object_status_and_throw_exception(*this);
434 void Context::set_font_options(const FontOptions& options)
436 cairo_set_font_options(m_cobject, options.cobj());
437 check_object_status_and_throw_exception(*this);
440 void Context::show_text(const std::string& utf8)
442 cairo_show_text(m_cobject, utf8.c_str());
443 check_object_status_and_throw_exception(*this);
446 void Context::show_glyphs(const std::vector<Glyph>& glyphs)
448 cairo_show_glyphs(m_cobject, const_cast<cairo_glyph_t*>(&glyphs[0]), glyphs.size());
449 check_object_status_and_throw_exception(*this);
452 RefPtr<FontFace> Context::get_font_face()
454 cairo_font_face_t* cfontface = cairo_get_font_face(m_cobject);
455 check_object_status_and_throw_exception(*this);
456 return RefPtr<FontFace>(new FontFace(cfontface, false /* does not have reference */));
459 RefPtr<const FontFace> Context::get_font_face() const
461 cairo_font_face_t* cfontface = cairo_get_font_face(m_cobject);
462 check_object_status_and_throw_exception(*this);
463 return RefPtr<const FontFace>(new FontFace(cfontface, false /* does not have reference */));
466 void Context::get_font_extents(FontExtents& extents) const
468 cairo_font_extents(m_cobject, &extents);
469 check_object_status_and_throw_exception(*this);
472 void Context::set_font_face(const RefPtr<const FontFace>& font_face)
474 cairo_set_font_face(m_cobject, const_cast<cairo_font_face_t*>(font_face->cobj()));
475 check_object_status_and_throw_exception(*this);
478 void Context::get_text_extents(const std::string& utf8, TextExtents& extents) const
480 cairo_text_extents(m_cobject, utf8.c_str(), &extents);
481 check_object_status_and_throw_exception(*this);
484 void Context::get_glyph_extents(const std::vector<Glyph>& glyphs, TextExtents& extents) const
486 cairo_glyph_extents(m_cobject, const_cast<cairo_glyph_t*>(&glyphs[0]), glyphs.size(), &extents);
487 check_object_status_and_throw_exception(*this);
490 void Context::text_path(const std::string& utf8)
492 cairo_text_path(m_cobject, utf8.c_str());
493 check_object_status_and_throw_exception(*this);
496 void Context::glyph_path(const std::vector<Glyph>& glyphs)
498 cairo_glyph_path(m_cobject, const_cast<cairo_glyph_t*>(&glyphs[0]), glyphs.size());
499 check_object_status_and_throw_exception(*this);
502 Operator Context::get_operator() const
504 const Operator result = static_cast<Operator>(cairo_get_operator(m_cobject));
505 check_object_status_and_throw_exception(*this);
509 RefPtr<Pattern> Context::get_source()
511 cairo_pattern_t* pattern = cairo_get_source(m_cobject);
512 check_object_status_and_throw_exception(*this);
513 return RefPtr<Pattern>(new Pattern(pattern, false /* does not have reference */));
516 RefPtr<const Pattern> Context::get_source() const
518 cairo_pattern_t* pattern = cairo_get_source(m_cobject);
519 check_object_status_and_throw_exception(*this);
520 return RefPtr<const Pattern>(new Pattern(pattern, false /* does not have reference */));
523 double Context::get_tolerance() const
525 const double result = cairo_get_tolerance(m_cobject);
526 check_object_status_and_throw_exception(*this);
530 Antialias Context::get_antialias() const
532 const Antialias result = static_cast<Antialias>(cairo_get_antialias(m_cobject));
533 check_object_status_and_throw_exception(*this);
537 void Context::get_current_point(double& x, double& y) const
539 cairo_get_current_point(m_cobject, &x, &y);
540 check_object_status_and_throw_exception(*this);
543 FillRule Context::get_fill_rule() const
545 const FillRule result = static_cast<FillRule>(cairo_get_fill_rule(m_cobject));
546 check_object_status_and_throw_exception(*this);
550 double Context::get_line_width() const
552 const double result = cairo_get_line_width(m_cobject);
553 check_object_status_and_throw_exception(*this);
557 LineCap Context::get_line_cap() const
559 const LineCap result = static_cast<LineCap>(cairo_get_line_cap(m_cobject));
560 check_object_status_and_throw_exception(*this);
564 LineJoin Context::get_line_join() const
566 const LineJoin result = static_cast<LineJoin>(cairo_get_line_join(m_cobject));
567 check_object_status_and_throw_exception(*this);
571 double Context::get_miter_limit() const
573 const double result = cairo_get_miter_limit(m_cobject);
574 check_object_status_and_throw_exception(*this);
578 void Context::get_matrix(Matrix& matrix)
580 cairo_get_matrix(m_cobject, &matrix);
581 check_object_status_and_throw_exception(*this);
584 RefPtr<Surface> Context::get_target()
586 cairo_surface_t* surface = cairo_get_target(const_cast<cairo_t*>(m_cobject));
587 check_object_status_and_throw_exception(*this);
588 return RefPtr<Surface>(new Surface(surface, false /* does not have reference */));
591 RefPtr<const Surface> Context::get_target() const
593 cairo_surface_t* surface = cairo_get_target(const_cast<cairo_t*>(m_cobject));
594 check_object_status_and_throw_exception(*this);
595 return RefPtr<const Surface>(new Surface(surface, false /* does not have reference */));
598 Path* Context::copy_path() const
600 cairo_path_t* cresult = cairo_copy_path(const_cast<cairo_t*>(m_cobject));
601 check_object_status_and_throw_exception(*this);
602 return new Path(cresult, true /* take ownership */); //The caller must delete it.
605 Path* Context::copy_path_flat() const
607 cairo_path_t* cresult = cairo_copy_path_flat(const_cast<cairo_t*>(m_cobject));
608 check_object_status_and_throw_exception(*this);
609 return new Path(cresult, true /* take ownership */); //The caller must delete it.
612 void Context::append_path(const Path& path)
614 cairo_append_path(m_cobject, const_cast<cairo_path_t*>(path.cobj()));
615 check_object_status_and_throw_exception(*this);
618 void Context::push_group()
620 cairo_push_group(m_cobject);
621 check_object_status_and_throw_exception(*this);
624 void Context::push_group_with_content(Content content)
626 cairo_push_group_with_content(m_cobject, static_cast<cairo_content_t>(content));
627 check_object_status_and_throw_exception(*this);
630 RefPtr<Pattern> Context::pop_group()
632 cairo_pattern_t* pattern = cairo_pop_group(m_cobject);
633 check_object_status_and_throw_exception(*this);
634 return RefPtr<Pattern>(new Pattern(pattern));
637 void Context::pop_group_to_source()
639 cairo_pop_group_to_source(m_cobject);
640 check_object_status_and_throw_exception(*this);
643 RefPtr<Surface> Context::get_group_target()
645 cairo_surface_t* surface = cairo_get_group_target(m_cobject);
646 // surface can be NULL if you're not between push/pop group calls
649 // FIXME: is this really the right way to handle this?
650 throw_exception(CAIRO_STATUS_NULL_POINTER);
652 return RefPtr<Surface>(new Surface(surface, false));
655 RefPtr<const Surface> Context::get_group_target() const
657 cairo_surface_t* surface = cairo_get_group_target(m_cobject);
658 // surface can be NULL if you're not between push/pop group calls
661 // FIXME: is this really the right way to handle this?
662 throw_exception(CAIRO_STATUS_NULL_POINTER);
664 return RefPtr<const Surface>(new Surface(surface, false));