[m-rev.] [PATCH 10/11] mercury_cairo: Add recording surfaces.
Peter Wang
novalazy at gmail.com
Fri Sep 4 12:00:58 AEST 2015
Add support for cairo recording surfaces.
extras/graphics/mercury_cairo/cairo.m:
Add type `rectangle_f', the float analogue of `rectangle'.
extras/graphics/mercury_cairo/cairo.recording.m:
New module.
extras/graphics/mercury_cairo/README:
Mention recording surfaces.
---
extras/graphics/mercury_cairo/README | 17 +-
extras/graphics/mercury_cairo/cairo.m | 9 +
extras/graphics/mercury_cairo/cairo.recording.m | 222 ++++++++++++++++++++++++
3 files changed, 240 insertions(+), 8 deletions(-)
create mode 100644 extras/graphics/mercury_cairo/cairo.recording.m
diff --git a/extras/graphics/mercury_cairo/README b/extras/graphics/mercury_cairo/README
index cc32fa4..ccd08f0 100644
--- a/extras/graphics/mercury_cairo/README
+++ b/extras/graphics/mercury_cairo/README
@@ -92,18 +92,19 @@ For example:
Backends Submodules
===================
-The Mercury binding has submodules that provide image, PDF, PostScript, and SVG
-surfaces. Each surface is represented by a type that is an instance of the
-cairo.surface/1 type class. For example, the interface to image surfaces is in
-the submodule "cairo.image".
-
-Image surfaces are always supported. PDF, PostScript, and SVG surfaces are
-optional. The following predicates may be used to test whether they are are
-supported by an installation:
+The Mercury binding has submodules that provide image, PDF, PostScript, SVG and
+recording surfaces. Each surface is represented by a type that is an instance
+of the cairo.surface/1 type class. For example, the interface to image
+surfaces is in the submodule "cairo.image".
+
+Image surfaces are always supported. PDF, PostScript, SVG and recording
+surfaces are optional. The following predicates may be used to test whether
+they are are supported by an installation:
cairo.pdf.have_pdf_surface/0
cairo.ps.have_ps_surface/0
cairo.svg.have_svg_surface/0
+ cairo.recording.have_recording_surface/0
(The predicate cairo.png.png_is_supported/0 performs the same function for
determining whether the PNG reading and writing capabilities in the submodule
diff --git a/extras/graphics/mercury_cairo/cairo.m b/extras/graphics/mercury_cairo/cairo.m
index bfc995e..5252e23 100644
--- a/extras/graphics/mercury_cairo/cairo.m
+++ b/extras/graphics/mercury_cairo/cairo.m
@@ -31,6 +31,7 @@
:- include_module pdf.
:- include_module png.
:- include_module ps.
+:- include_module recording.
:- include_module region.
:- include_module surface.
:- include_module svg.
@@ -114,6 +115,14 @@
rect_height :: int % Height
).
+:- type rectangle_f
+ ---> rectangle_f(
+ rectf_x :: float,
+ rectf_y :: float,
+ rectf_width :: float,
+ rectf_height :: float
+ ).
+
%---------------------------------------------------------------------------%
%
% Error handling
diff --git a/extras/graphics/mercury_cairo/cairo.recording.m b/extras/graphics/mercury_cairo/cairo.recording.m
new file mode 100644
index 0000000..4312008
--- /dev/null
+++ b/extras/graphics/mercury_cairo/cairo.recording.m
@@ -0,0 +1,222 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%---------------------------------------------------------------------------%
+% Copyright (C) 2015 The Mercury team.
+% This file may only be copied under the terms of the GNU Library General
+% Public License - see the file COPYING.LIB in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% Author: Peter Wang
+%
+% This sub-module provides recording surfaces.
+%
+%---------------------------------------------------------------------------%
+
+:- module cairo.recording.
+:- interface.
+
+:- import_module maybe.
+
+%---------------------------------------------------------------------------%
+
+:- type recording_surface.
+
+:- instance surface(recording_surface).
+
+%---------------------------------------------------------------------------%
+
+ % recording.have_recording_surface:
+ % Succeeds if recording surfaces are supported by this implementation.
+ %
+:- pred have_recording_surface is semidet.
+
+ % recording.create_surface(Content, MaybeExtents, Surface, !IO):
+ % Surface is a new recording surface.
+ % Throws a cairo.error/0 exception if the surface cannot be created.
+ %
+:- pred create_surface(content::in, maybe(rectangle_f)::in,
+ recording_surface::out, io::di, io::uo) is det.
+
+ % recording.ink_extents(Surface, X0, Y0, Width, Height):
+ % Measures the extents of the operations stored within the recording
+ % surface.
+ %
+:- pred ink_extents(recording_surface::in, float::out, float::out,
+ float::out, float::out, io::di, io::uo) is det.
+
+ % recording.get_extents(Surface, MaybeExtents):
+ % Get the extents of the recording surface.
+ %
+:- pred get_extents(recording_surface::in, maybe(rectangle_f)::out,
+ io::di, io::uo) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- pragma foreign_decl("C", "#include \"cairo.mh\"").
+
+:- pragma foreign_type("C", recording_surface, "MCAIRO_surface *",
+ [can_pass_as_mercury_type]).
+
+:- instance surface(recording_surface) where [].
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+ have_recording_surface,
+ [promise_pure, will_not_call_mercury],
+"
+#if defined(CAIRO_HAS_RECORDING_SURFACE)
+ SUCCESS_INDICATOR = MR_TRUE;
+#else
+ SUCCESS_INDICATOR = MR_FALSE;
+#endif
+").
+
+%-----------------------------------------------------------------------------%
+%
+% Recording surface creation
+%
+
+create_surface(Content, MaybeExtents, Surface, !IO) :-
+ (
+ MaybeExtents = yes(rectangle_f(X, Y, W, H)),
+ HaveExtents = yes
+ ;
+ MaybeExtents = no,
+ HaveExtents = no,
+ X = 0.0,
+ Y = 0.0,
+ W = 0.0,
+ H = 0.0
+ ),
+ create_surface_2(Content, HaveExtents, X, Y, W, H, Supported, Status,
+ Surface, !IO),
+ (
+ Supported = yes,
+ ( Status = status_success ->
+ true
+ ;
+ throw(cairo.error("recording.create_surface/4", Status))
+ )
+ ;
+ Supported = no,
+ throw(cairo.unsupported_surface_error("recording"))
+ ).
+
+:- pred create_surface_2(content::in, bool::in, float::in, float::in,
+ float::in, float::in, bool::out, cairo.status::out, recording_surface::out,
+ io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+ create_surface_2(Content::in, HaveExtents::in, X::in, Y::in,
+ W::in, H::in, Supported::out, Status::out, Surface::out,
+ _IO0::di, _IO::uo),
+ [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+#if defined(CAIRO_HAS_RECORDING_SURFACE)
+
+ cairo_surface_t *raw_surface;
+
+ Supported = MR_YES;
+ if (HaveExtents) {
+ cairo_rectangle_t rect = {X, Y, W, H};
+ raw_surface = cairo_recording_surface_create(Content, &rect);
+ } else {
+ raw_surface = cairo_recording_surface_create(Content, NULL);
+ }
+
+ Status = cairo_surface_status(raw_surface);
+
+ switch (Status) {
+ case CAIRO_STATUS_SUCCESS:
+ Surface = MR_GC_NEW(MCAIRO_surface);
+ Surface->mcairo_raw_surface = raw_surface;
+ MR_GC_register_finalizer(Surface, MCAIRO_finalize_surface, 0);
+ break;
+
+ case CAIRO_STATUS_NULL_POINTER:
+ case CAIRO_STATUS_NO_MEMORY:
+ case CAIRO_STATUS_READ_ERROR:
+ case CAIRO_STATUS_INVALID_CONTENT:
+ case CAIRO_STATUS_INVALID_FORMAT:
+ case CAIRO_STATUS_INVALID_VISUAL:
+ Surface = NULL;
+ break;
+
+ default:
+ MR_external_fatal_error(\"Mercury cairo\", \"invalid status\");
+ }
+#else
+ Supported = MR_NO;
+ Status = CAIRO_STATUS_SUCCESS;
+ Surface = NULL;
+#endif
+").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+ ink_extents(Surface::in, X::out, Y::out, W::out, H::out,
+ _IO0::di, _IO::uo),
+ [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+#if defined(CAIRO_HAS_RECORDING_SURFACE)
+ double x, y, w, h;
+
+ cairo_recording_surface_ink_extents(Surface->mcairo_raw_surface,
+ &x, &y, &w, &h);
+ X = x;
+ Y = y;
+ W = w;
+ H = h;
+#else
+ MR_external_fatal_error(\"Mercury cairo\",
+ \"Recording surfaces not supported by this installation\");
+#endif
+").
+
+%---------------------------------------------------------------------------%
+
+get_extents(Surface, MaybeExtents, !IO) :-
+ get_extents_2(Surface, Ok, X, Y, W, H, !IO),
+ (
+ Ok = yes,
+ MaybeExtents = yes(rectangle_f(X, Y, W, H))
+ ;
+ Ok = no,
+ MaybeExtents = no
+ ).
+
+:- pred get_extents_2(recording_surface::in, bool::out, float::out, float::out,
+ float::out, float::out, io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+ get_extents_2(Surface::in, Ok::out, X::out, Y::out, W::out, H::out,
+ _IO0::di, _IO::uo),
+ [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+ cairo_rectangle_t rect;
+
+ if (cairo_recording_surface_get_extents(Surface->mcairo_raw_surface,
+ &rect))
+ {
+ Ok = MR_YES;
+ X = rect.x;
+ Y = rect.y;
+ W = rect.width;
+ H = rect.height;
+ } else {
+ Ok = MR_NO;
+ X = 0.0;
+ Y = 0.0;
+ W = 0.0;
+ H = 0.0;
+ }
+").
+
+%---------------------------------------------------------------------------%
+:- end_module cairo.recording.
+%---------------------------------------------------------------------------%
--
2.1.2
More information about the reviews
mailing list