summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Rhinelander <jason@imaginary.ca>2016-01-28 11:33:01 -0500
committerMurray Cumming <murrayc@murrayc.com>2016-04-10 10:48:56 +0200
commit14bda0b09cd1650b46c758d2b0a9dbae8f007d62 (patch)
tree0048133e26ff757e2280a0becff3be155b50750f
parent80a6e536d13792e4e9f13606a0f1d2d2f6a73c2e (diff)
Added C++ wrapper around cairo_recording_surface
Bug #121359
-rw-r--r--cairomm/surface.cc41
-rw-r--r--cairomm/surface.h101
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