diff options
author | Jason Rhinelander <jason@imaginary.ca> | 2016-01-28 11:33:01 -0500 |
---|---|---|
committer | Murray Cumming <murrayc@murrayc.com> | 2016-04-10 10:48:56 +0200 |
commit | 14bda0b09cd1650b46c758d2b0a9dbae8f007d62 (patch) | |
tree | 0048133e26ff757e2280a0becff3be155b50750f | |
parent | 80a6e536d13792e4e9f13606a0f1d2d2f6a73c2e (diff) |
Added C++ wrapper around cairo_recording_surface
Bug #121359
-rw-r--r-- | cairomm/surface.cc | 41 | ||||
-rw-r--r-- | cairomm/surface.h | 101 |
2 files changed, 142 insertions, 0 deletions
diff --git a/cairomm/surface.cc b/cairomm/surface.cc index edeb289..e24dca1 100644 --- a/cairomm/surface.cc +++ b/cairomm/surface.cc @@ -378,6 +378,47 @@ int ImageSurface::format_stride_for_width (Cairo::Format format, int width) } +RecordingSurface::RecordingSurface(cairo_surface_t* cobject, bool has_reference) +: Surface(cobject, has_reference) +{ } + +RecordingSurface::~RecordingSurface() +{ + // surface is destroyed in base class +} + +RefPtr<RecordingSurface> RecordingSurface::create(Content content) +{ + auto cobject = cairo_recording_surface_create((cairo_content_t)content, NULL); + check_status_and_throw_exception(cairo_surface_status(cobject)); + return RefPtr<RecordingSurface>(new RecordingSurface(cobject, true /* has reference */)); +} + +RefPtr<RecordingSurface> RecordingSurface::create(const Rectangle& extents, Content content) +{ + auto cobject = cairo_recording_surface_create((cairo_content_t)content, &extents); + check_status_and_throw_exception(cairo_surface_status(cobject)); + return RefPtr<RecordingSurface>(new RecordingSurface(cobject, true /* has reference */)); +} + +Rectangle RecordingSurface::ink_extents() const +{ + Rectangle inked; + cairo_recording_surface_ink_extents(const_cast<cobject*>(cobj()), + &inked.x, &inked.y, &inked.width, &inked.height); + check_object_status_and_throw_exception(*this); + return inked; +} + +bool RecordingSurface::get_extents(Rectangle &extents) const +{ + bool has_extents = cairo_recording_surface_get_extents(const_cast<cobject*>(cobj()), + &extents); + check_object_status_and_throw_exception(*this); + return has_extents; +} + + /******************************************************************************* * THE FOLLOWING SURFACE TYPES ARE EXPERIMENTAL AND NOT FULLY SUPPORTED ******************************************************************************/ diff --git a/cairomm/surface.h b/cairomm/surface.h index dc72b08..b98cb1a 100644 --- a/cairomm/surface.h +++ b/cairomm/surface.h @@ -584,6 +584,107 @@ public: }; +/** + * A recording surface is a surface that records all drawing operations at the + * highest level of the surface backend interface, (that is, the level of paint, + * mask, stroke, fill, and show_text_glyphs). The recording surface can then be + * "replayed" against any target surface by using it as a source surface. + * + * If you want to replay a surface so that the results in `target` will be + * identical to the results that would have been obtained if the original + * operations applied to the recording surface had instead been applied to the + * target surface, you can use code like this: + * + * Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create(target); + * context->set_source(recording_surface, 0.0, 0.0); + * context->paint(); + * + * A recording surface is logically unbounded, i.e. it has no implicit + * constraint on the size of the drawing surface. However, in practice this is + * rarely useful as you wish to replay against a particular target surface with + * known bounds. For this case, it is more efficient to specify the target + * extents to the recording surface upon creation. + * + * The recording phase of the recording surface is careful to snapshot all + * necessary objects (paths, patterns, etc.), in order to achieve accurate + * replay. + * + * Note that like all surfaces, a RecordingSurface is a reference-counted object + * that should be used via Cairo::RefPtr. + */ +class RecordingSurface : public Surface +{ +public: + + /** + * Create a C++ wrapper for the C instance. This C++ instance should then be + * given to a RefPtr. + * @param cobject The C instance. + * @param has_reference Whether we already have a reference. Otherwise, the + * constructor will take an extra reference. + */ + explicit RecordingSurface(cairo_surface_t* cobject, bool has_reference = false); + + virtual ~RecordingSurface(); + + /** + * Measures the extents of the operations stored within the recording + * surface. This is useful to compute the required size of an image surface + * (or equivalent) into which to replay the full sequence of drawing + * operations. + * @return a Rectangle with `x` and `y` set to the coordinates of the top-left + * of the ink bounding box, and `width` and `height` set to the width and + * height of the ink bounding box. + */ + Rectangle ink_extents() const; + + /** + * Get the extents of the recording surface, if the surface is bounded. + * @param extents the Rectangle in which to store the extents if the recording + * surface is bounded + * @return true if the recording surface is bounded, false if the recording + * surface is unbounded (in which case `extents` will not be set). + */ + bool get_extents(Rectangle &extents) const; + + /** + * Creates a recording surface which can be used to record all drawing + * operations at the highest level (that is, the level of paint, mask, stroke, + * fill and show_text_glyphs). The recording surface can then be "replayed" + * against any target surface by using it as a source to drawing operations. + * The recording surface will be unbounded. + * + * The recording phase of the recording surface is careful to snapshot all + * necessary objects (paths, patterns, etc.), in order to achieve accurate + * replay. + * + * @param content the content of the recording surface; defaults to + * Cairo::Content::CONTENT_COLOR_ALPHA. + * @return a RefPtr to the newly created recording surface. + */ + static RefPtr<RecordingSurface> create(Content content = Content::CONTENT_COLOR_ALPHA); + + /** + * Creates a recording surface which can be used to record all drawing + * operations at the highest level (that is, the level of paint, mask, stroke, + * fill and show_text_glyphs). The recording surface can then be "replayed" + * against any target surface by using it as a source to drawing operations. + * The recording surface will be bounded by the given rectangle. + * + * The recording phase of the recording surface is careful to snapshot all + * necessary objects (paths, patterns, etc.), in order to achieve accurate + * replay. + * + * @param extents the extents to record + * @param content the content of the recording surface; defaults to + * Cairo::Content::CONTENT_COLOR_ALPHA. + * @return a RefPtr to the newly created recording surface. + */ + static RefPtr<RecordingSurface> create(const Rectangle& extents, Content content = Content::CONTENT_COLOR_ALPHA); + +}; + + #ifdef CAIRO_HAS_PDF_SURFACE /** @example pdf-surface.cc |