[m-rev.] diff: more work on the cairo binding

Julien Fischer juliensf at csse.unimelb.edu.au
Thu Sep 9 03:32:43 AEST 2010


Extend the cairo binding to support features added in more recent
versions of cairo.

extras/graphics/mercury_cairo/cairo.m:
 	Support the rgb16_565 format.

 	Add a Mercury binding for the new function cairo_in_clip().

 	Be more consistent about type variable names.

 	Add some stuff for supporting regions.

extras/graphics/mercury_cairo/cario.region.m:
 	A new sub-module that provides a Mercury interface to
 	the regions API added in cairo 1.10.

Index: cairo.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/extras/graphics/mercury_cairo/cairo.m,v
retrieving revision 1.1
diff -u -r1.1 cairo.m
--- cairo.m	5 Sep 2010 14:31:44 -0000	1.1
+++ cairo.m	8 Sep 2010 17:29:49 -0000
@@ -31,6 +31,7 @@
  :- include_module pdf.
  :- include_module png.
  :- include_module ps.
+:- include_module region.
  :- include_module surface.
  :- include_module svg.
  :- include_module text.
@@ -61,11 +62,13 @@

  :- type cairo.font_options.

+:- type cairo.region.
+
      % TODO: scaled fonts are NYI.
      %
  :- type cairo.scaled_font(F).   % <= font_face(F).

-    % Values of this type descirbe that content that a surface will contain.
+    % Values of this type describe that content that a surface will contain.
      %
  :- type content
      --->    content_color
@@ -94,9 +97,23 @@
      ;       format_a8
              % Each pixel is a 8-bit quantity holding an alpha value.

-    ;       format_a1.
+    ;       format_a1
              % Each pixel is a 1-bit quantity holding an alpha value.

+    ;       format_rgb16_565.
+            % Each pixel is a 16-bit quantity with red in the upper 5 bits,
+            % then green in the middle 6 bits, and blue in the lower 5 bits.
+
+    % A rectangle with integer coordinates.
+    %
+:- type rectangle
+    --->    rectangle(
+                rect_x :: int,      % X coordinate of the LHS.
+                rect_y :: int,      % Y coordinate of the top.
+                rect_width  :: int, % Width.
+                rect_height :: int  % Height
+            ).
+
  %---------------------------------------------------------------------------%
  %
  % Error handling
@@ -156,6 +173,12 @@
      ;       status_no_memory
      ;       status_pattern_type_mismatch.

+    % Status information for regions.
+    %
+:- inst cairo.region_status
+    --->    status_success
+    ;       status_no_memory.
+
      % Exceptions of this type are thrown to indicate a cairo error.
      %
  :- type cairo.error
@@ -350,17 +373,17 @@
      % cairo.get_line_width(Context, Width, !IO):
      % Width is the current line width for Context.
      %
-:- pred get_line_width(context(T)::in, float::out, io::di, io::uo) is det.
+:- pred get_line_width(context(S)::in, float::out, io::di, io::uo) is det.

      % cairo.set_miter_limit(Context, Limit, !IO):
      % Set the miter limit for Context to Limit.
      %
-:- pred set_miter_limit(context(T)::in, float::in, io::di, io::uo) is det.
+:- pred set_miter_limit(context(S)::in, float::in, io::di, io::uo) is det.

      % cairo.get_miter_limit(Context, Limit, !IO):
      % Limit is the miter limit for Context.
      %
-:- pred get_miter_limit(context(T)::in, float::out, io::di, io::uo) is det.
+:- pred get_miter_limit(context(S)::in, float::out, io::di, io::uo) is det.

      % Values of this type specify the compositing operator used for drawing
      % operations (See: <http://cairographics.org/operators/> for details.)
@@ -383,20 +406,20 @@
      % cairo.set_operator(Context, Operator, !IO):
      % Set the compositing operator for Context to Operator.
      %
-:- pred set_operator(context(T)::in, operator::in, io::di, io::uo) is det.
+:- pred set_operator(context(S)::in, operator::in, io::di, io::uo) is det.

      % cairo.get_operator(Context, Operator, !IO):
      % Operator is the current compositing operator for Context.
      %
-:- pred get_operator(context(T)::in, operator::out, io::di, io::uo) is det.
+:- pred get_operator(context(S)::in, operator::out, io::di, io::uo) is det.

      % cairo.set_tolerance(Context, Tolerance, !IO):
      %
-:- pred set_tolerance(context(T)::in, float::in, io::di, io::uo) is det.
+:- pred set_tolerance(context(S)::in, float::in, io::di, io::uo) is det.

      % cairo.get_tolerance(Context, Tolerance, !IO):
      %
-:- pred get_tolerance(context(T)::in, float::out, io::di, io::uo) is det.
+:- pred get_tolerance(context(S)::in, float::out, io::di, io::uo) is det.

      % cairo.clip(Context, !IO):
      % Establishes a new clip region by intersecting the current clip region
@@ -404,20 +427,27 @@
      % to the current fill rule.
      % The current path will be cleared from Context.
      %
-:- pred clip(context(T)::in, io::di, io::uo) is det.
+:- pred clip(context(S)::in, io::di, io::uo) is det.

      % cairo.clip_preserve(Context, !IO):
      % As above, but do not clear the current path from Context.
      %
-:- pred clip_preserve(context(T)::in, io::di, io::uo) is det.
+:- pred clip_preserve(context(S)::in, io::di, io::uo) is det.

      % cairo.clip_extents(Context, Left, Top, Right, Bottom, !IO):
      % Compute a bounding box in user coordinates covering the area inside the
      % current clip for Context.
      %
-:- pred clip_extents(context(T)::in, float::out, float::out,
+:- pred clip_extents(context(S)::in, float::out, float::out,
      float::out, float::out, io::di, io::uo) is det.

+    % cairo.in_clip(Context, X, Y Result, !IO):
+    % Result is "yes" if the point (X, Y) is inside the area that
+    % would be visible through the current clip for Context.
+    %
+:- pred in_clip(context(S)::in, float::in, float::in, bool::out,
+    io::di, io::uo) is det.
+
      % cairo.reset_clip(Context, !IO):
      % Reset the current clip region to its original, unrestricted state.
      %
@@ -428,7 +458,7 @@
      % (Each sub-path is implicitly closed before being filled.)
      % The current path for Context will be cleared.
      %
-:- pred fill(context(T)::in, io::di, io::uo) is det.
+:- pred fill(context(S)::in, io::di, io::uo) is det.

      % cairo.fill_preserve(Context, !IO):
      % As above, but preserve the current path for Context.
@@ -442,7 +472,7 @@
      % an empty rectangle ((0,0), (0,0)). Surface dimensions and clipping are
      % not taken into account.
      %
-:- pred fill_extents(context(T)::in, float::out, float::out,
+:- pred fill_extents(context(S)::in, float::out, float::out,
      float::out, float::out, io::di, io::uo) is det.

      % cairo.in_fill(Context, X, Y, Result, !IO):
@@ -450,43 +480,43 @@
      % would be affected by a cairo.fill/3 operation given the current
      % path and filling parameters.  Result is "no" otherwise.
      %
-:- pred in_fill(context(T)::in, float::in, float::in, bool::out,
+:- pred in_fill(context(S)::in, float::in, float::in, bool::out,
      io::di, io::uo) is det.

      % cairo.mask(Context, Pattern, !IO):
      % Paint the current source using the alpha channel of Pattern as a mask.
      %
-:- pred mask(context(T)::in, pattern::in, io::di, io::uo) is det.
+:- pred mask(context(S)::in, pattern::in, io::di, io::uo) is det.

      % cairo.mask_surface(Context, Surface, X, Y, !IO):
      % Paint the current source using the alpha channel of Surface as a mask.
      % (X, Y) is coordinate at which to place the origin of Surface.
      %
-:- pred mask_surface(context(T)::in, S::in, float::in, float::in,
-    io::di, io::uo) is det <= surface(S).
+:- pred mask_surface(context(S)::in, Mask::in, float::in, float::in,
+    io::di, io::uo) is det <= surface(Mask).

      % cairo.paint(Context, !IO):
      % Paint the current source everywhere within the current clip region.
      %
-:- pred paint(context(T)::in, io::di, io::uo) is det.
+:- pred paint(context(S)::in, io::di, io::uo) is det.

      % cairo.paint_with_alpha(Context, Alpha, !IO):
      % Paint the current source everywhere within the current clip region using
      % a mask of constant alpha value Alpha.
      %
-:- pred paint_with_alpha(context(T)::in, float::in, io::di, io::uo) is det.
+:- pred paint_with_alpha(context(S)::in, float::in, io::di, io::uo) is det.

      % cairo.stroke(Context, !IO):
      % Stork the current path according to the current line width, line join,
      % line cap, and dash settings for Context.
      % The current path will be cleared.
      %
-:- pred stroke(context(T)::in, io::di, io::uo) is det.
+:- pred stroke(context(S)::in, io::di, io::uo) is det.

      % cairo.stroke_preserve(Context, !IO):
      % As above, but preserve the current path for Context.
      %
-:- pred stroke_preserve(context(T)::in, io::di, io::uo) is det.
+:- pred stroke_preserve(context(S)::in, io::di, io::uo) is det.

      % cairo.stroke_extents(Context, Left, Top, Right, Bottom, !IO):
      % Compute a bounding box in user coordinates covering the area that would
@@ -495,7 +525,7 @@
      % an empty rectangle ((0,0), (0,0)).
      % Surface dimensions and clipping are not taken into account.
      %
-:- pred stroke_extents(context(T)::in, float::out, float::out,
+:- pred stroke_extents(context(S)::in, float::out, float::out,
      float::out, float::out, io::di, io::uo) is det.

      % cairo.in_stroke(Context, X, Y, Result, !IO):
@@ -503,7 +533,7 @@
      % be affected by a cairo.stroke/3 operation given the current path and
      % stroking parameters.
      %
-:- pred in_stroke(context(T)::in, float::in, float::in, bool::out,
+:- pred in_stroke(context(S)::in, float::in, float::in, bool::out,
      io::di, io::uo) is det.

      % cairo.copy_page(Context, !IO):
@@ -512,13 +542,13 @@
      % for the next page too. Use cairo.show_page/3 if you want to get an empty
      % page after the emission.
      %
-:- pred copy_page(context(T)::in, io::di, io::uo) is det.
+:- pred copy_page(context(S)::in, io::di, io::uo) is det.

      % cairo.show_page(Context, !IO):
      % Emits and clears the current page for backends that support multiple
      % pages.
      %
-:- pred show_page(context(T)::in, io::di, io::uo) is det.
+:- pred show_page(context(S)::in, io::di, io::uo) is det.

  %---------------------------------------------------------------------------%

@@ -534,11 +564,17 @@
      io::di, io::uo) is det <= surface(S).

      % cairo.pattern_status(Pattern, Status, !IO):
-    % Satus is the current status of Pattern.
+    % Status is the current status of Pattern.
      %
  :- pred pattern_status(pattern::in, status::out(pattern_status),
      io::di, io::uo) is det.

+    % cairo.region_status(Region, Status, !IO):
+    % Status is the current status of Region.
+    %
+:- pred region_status(region::in, status::out(region_status),
+    io::di, io::uo) is det.
+
      % cairo.status_to_string(Status) = String:
      % String is a human-readable description of Status.
      %
@@ -592,6 +628,10 @@
      cairo_scaled_font_t *mcairo_raw_scaled_font;
  } MCAIRO_scaled_font;

+typedef struct {
+    cairo_region_t      *mcairo_raw_region;
+} MCAIRO_region;
+
  extern void
  MCAIRO_finalize_context(void *context, void *client_data);

@@ -611,6 +651,9 @@
  MCAIRO_finalize_font_options(void *font_options, void *client_data);

  extern void
+MCAIRO_finalize_region(void *region, void *client_data);
+
+extern void
  MCAIRO_finalize_scaled_font(void *scaled_font, void *client_data);

  ").
@@ -634,6 +677,9 @@
  :- pragma foreign_type("C", cairo.font_options, "MCAIRO_font_options *",
      [can_pass_as_mercury_type]).

+:- pragma foreign_type("C", cairo.region, "MCAIRO_region *",
+    [can_pass_as_mercury_type]).
+
  :- pragma foreign_type("C", cairo.scaled_font(F), "MCAIRO_scaled_font *",
      [can_pass_as_mercury_type]).

@@ -662,10 +708,11 @@
  ]).

  :- pragma foreign_enum("C", cairo.format/0, [
-    format_argb32 - "CAIRO_FORMAT_ARGB32",
-    format_rgb24  - "CAIRO_FORMAT_RGB24",
-    format_a8     - "CAIRO_FORMAT_A8",
-    format_a1     - "CAIRO_FORMAT_A1"
+    format_argb32    - "CAIRO_FORMAT_ARGB32",
+    format_rgb24     - "CAIRO_FORMAT_RGB24",
+    format_a8        - "CAIRO_FORMAT_A8",
+    format_a1        - "CAIRO_FORMAT_A1",
+    format_rgb16_565 - "CAIRO_FORMAT_RGB16_565"
  ]).

  :- pragma foreign_enum("C", cairo.status/0, [
@@ -743,6 +790,12 @@
  }

  void
+MCAIRO_finalize_region(void *region, void *client_data)
+{
+    cairo_region_destroy(((MCAIRO_region *)region)->mcairo_raw_region);
+}
+
+void
  MCAIRO_finalize_scaled_font(void *scaled_font, void *client_data)
  {
      cairo_scaled_font_destroy(
@@ -1122,6 +1175,17 @@
  ").

  :- pragma foreign_proc("C",
+    in_clip(Ctxt::in, X::in, Y::in, Result::out, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    if (cairo_in_clip(Ctxt->mcairo_raw_context, X, Y)) {
+        Result = MR_YES;
+    } else {
+        Result = MR_NO;
+    }
+").
+
+:- pragma foreign_proc("C",
      reset_clip(Ctxt::in, _IO0::di, _IO::uo),
      [promise_pure, will_not_call_mercury],
  "
@@ -1251,6 +1315,14 @@
  ").

  :- pragma foreign_proc("C",
+    region_status(Region::in, Status::out(region_status),
+        _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    Status = cairo_region_status(Region->mcairo_raw_region);
+").
+
+:- pragma foreign_proc("C",
     status_to_string(Status::in) = (Str::out),
     [promise_pure, will_not_call_mercury],
  "
Index: cairo.region.m
===================================================================
RCS file: cairo.region.m
diff -N cairo.region.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ cairo.region.m	8 Sep 2010 17:29:49 -0000
@@ -0,0 +1,438 @@
+%----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%----------------------------------------------------------------------------%
+% Copyright (C) 2010 The University of Melbourne.
+% 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: Julien Fischer <juliensf at csse.unimelb.edu.au>
+%
+%-----------------------------------------------------------------------------%
+
+:- module cairo.region.
+:- interface.
+
+%-----------------------------------------------------------------------------%
+
+    % region.create(Region, !IO):
+    % Region is a new empty region.
+    %
+:- pred create(region::out, io::di, io::uo) is det.
+ 
+    % region.create_rectangle(Rectangle, Region, !IO):
+    % Region is a new region containing Rectangle.
+    %
+:- pred create_rectangle(rectangle::in, region::out,
+    io::di, io::uo) is det.
+
+    % region.create_rectangles(Rectangles, Region, !IO):
+    % Region is a new region that containing the union of
+    % Rectangles.
+    %
+    % XXX NYI
+%:- pred create_rectangles(list(rectangle)::in, region::out,
+%    io::di, io::uo) is det.
+
+    % region.copy(Orig, Copy, !IO):
+    % Copy is a copy of Orig.
+    %
+:- pred copy(region::in, region::out, io::di, io::uo) is det.
+
+    % region.get_extents(Region, Rectangle, !IO):
+    % Rectangle is the bounding rectangle for Region.
+    %
+:- pred get_extents(region::in, rectangle::out,
+    io::di, io::uo) is det.
+
+    % region.num_rectangles(Region, NumRectangles, !IO):
+    % NumRectangles is the number of rectangles in Region.
+    %
+:- pred num_rectangles(region::in, int::out, io::di, io::uo) is det.
+
+    % region.get_rectangle(Region, N, Rectangle, !IO):
+    % Rectangle is the N'th rectangle in Region.
+    % XXX the cairo manual doesn't say what happens if there
+    % are less than N rectangles in Region.
+    %
+:- pred get_rectangle(region::in, int::in, rectangle::out,
+    io::di, io::uo) is det.
+
+    % region.is_empty(Region, IsEmpty, !IO):
+    % IsEmpty is "yes" if Region is empty and "no" otherwise.
+    %
+:- pred is_empty(region::in, bool::out, io::di, io::uo) is det.
+
+    % region.contains_point(Region, X, Y, Result, !IO):
+    % Result is "yes" if (X, Y) is contained in Region.
+    %
+:- pred contains_point(region::in, int::in, int::in, bool::out,
+    io::di, io::uo) is det.
+
+:- type region.overlap
+    --->    overlap_in
+            % The contents are entirely inside the region.
+
+    ;       overlap_out
+            % The contents are entirely outside the region.
+
+    ;       overlap_part.
+            % The contents are partially inside and partially outside
+            % the region.
+
+    % region.contains_rectangle(Region, Rectangle, Overlap, !IO):
+    % Overlap is the result of checking whether Rectangle is (partially)
+    % contained within Region.
+    %
+:- pred contains_rectangle(region::in, rectangle::in, overlap::out,
+    io::di, io::uo) is det.
+
+    % region.equal(RegionA, RegionB, Result, !IO):
+    % Result is "yes" if RegionA and RegionB contain the some coverage
+    % and "no" otherwise.
+    %
+:- pred equal(region::in, region::in, bool::out, io::di, io::uo) is det.
+
+    % region.translate(Region, Dx, Dy, !IO):
+    % Translate Region by (Dx, Dy).
+    %
+:- pred translate(region::in, int::in, int::in, io::di, io::uo) is det.
+ 
+    % region.intersect(Dst, Other, !IO):
+    % Update Dst to be the intersection of Dst and Other.
+    %
+:- pred intersect(region::in, region::in, io::di, io::uo) is det.
+ 
+    % region.intersect_rectangle(Region, Rectangle, !IO):
+    % Update Region to be the intersection of Region and Rectangle.
+    %
+:- pred intersect_rectangle(region::in, rectangle::in, io::di, io::uo) is det.
+
+    % region.subtract(Dst, Other, !IO):
+    % Update Dst to be the result of subtracting Other from Dst.
+    %
+:- pred subtract(region::in, region::in, io::di, io::uo) is det.
+ 
+    % region.subtract_rectangle(Region, Rectangle, !IO):
+    % Update Region to be the result of subtracting Rectangle from Region.
+    %
+:- pred subtract_rectangle(region::in, rectangle::in, io::di, io::uo) is det.
+
+    % region.union(Dst, Other, !IO):
+    % Update Dst to be the union of Dst and Other.
+    %
+:- pred union(region::in, region::in, io::di, io::uo) is det.
+ 
+    % region.union_rectangle(Region, Rectangle, !IO):
+    % Update Region to be the union of Region and Rectangle.
+    %
+:- pred union_rectangle(region::in, rectangle::in, io::di, io::uo) is det.
+ 
+    % region.xor(Dst, Other, !IO):
+    % Update Dst to be the exclusive difference of Dst and Other.
+    %
+:- pred xor(region::in, region::in, io::di, io::uo) is det.
+
+    % region.xor_rectangle(Region, Rectangle, !IO):
+    % Update Region to be the exclusive difference of Region and Rectangle.
+    %
+:- pred xor_rectangle(region::in, rectangle::in, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- pragma foreign_enum("C", region.overlap/0, [
+    overlap_in   - "CAIRO_REGION_OVERLAP_IN",
+    overlap_out  - "CAIRO_REGION_OVERLAP_OUT",
+    overlap_part - "CAIRO_REGION_OVERLAP_PART"
+]).
+
+%-----------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    create(Region::out, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_region_t  *raw_region;
+ 
+    raw_region = cairo_region_create();
+    Region = MR_GC_NEW(MCAIRO_region);
+    Region->mcairo_raw_region = raw_region;
+    MR_GC_register_finalizer(Region, MCAIRO_finalize_region, 0);
+").
+
+create_rectangle(Rectangle, Region, !IO) :-
+    Rectangle = rectangle(X, Y, Width, Height),
+    create_rectangle_2(X, Y, Width, Height, Region, !IO).
+
+:- pred create_rectangle_2(int::in, int::in, int::in, int::in,
+    region::out, io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+    create_rectangle_2(X::in, Y::in, W::in, H::in, Region::out,
+        _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_rectangle_int_t   rect;
+    cairo_region_t          *raw_region;
+
+    rect.x = X;
+    rect.y = Y;
+    rect.width = W;
+    rect.height = H;
+
+    raw_region = cairo_region_create_rectangle(&rect);
+    Region = MR_GC_NEW(MCAIRO_region);
+    Region->mcairo_raw_region = raw_region;
+    MR_GC_register_finalizer(Region, MCAIRO_finalize_region, 0);
+").
+
+:- pragma foreign_proc("C",
+    copy(Orig::in, Copy::out, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_region_t  *raw_copy;
+    raw_copy = cairo_region_copy(Orig->mcairo_raw_region);
+    Copy = MR_GC_NEW(MCAIRO_region);
+    Copy->mcairo_raw_region = raw_copy;
+    MR_GC_register_finalizer(Copy, MCAIRO_finalize_region, 0);
+").
+
+get_extents(Region, Rectangle, !IO) :-
+    get_extents_2(Region, X, Y, Width, Height, !IO),
+    Rectangle = rectangle(X, Y, Width, Height).
+ 
+:- pred get_extents_2(region::in, int::out, int::out,
+    int::out, int::out, io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+    get_extents_2(Region::in, X::out, Y::out, W::out, H::out,
+        _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_rectangle_int_t   r;
+    cairo_region_get_extents(Region->mcairo_raw_region,
+        &r);
+    X = r.x;
+    Y = r.y;
+    W = r.width;
+    H = r.height; 
+").
+
+:- pragma foreign_proc("C",
+    num_rectangles(Region::in, NR::out, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    NR = cairo_region_num_rectangles(Region->mcairo_raw_region);
+").
+
+get_rectangle(Region, N, Rectangle, !IO) :-
+    get_rectangle_2(Region, N, X, Y, Height, Width, !IO),
+    Rectangle = rectangle(X, Y, Height, Width).
+
+:- pred get_rectangle_2(region::in, int::in, int::out, int::out,
+    int::out, int::out, io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+    get_rectangle_2(Region::in, N::in, X::out, Y::out, W::out,
+        H::out, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_rectangle_int_t     r; 
+
+    cairo_region_get_rectangle(Region->mcairo_raw_region,
+        N, &r);
+    X = r.x;
+    Y = r.y;
+    W = r.width;
+    H = r.height;
+").
+
+:- pragma foreign_proc("C",
+    is_empty(Region::in, IsEmpty::out, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    if (cairo_region_is_empty(Region->mcairo_raw_region)) {
+        IsEmpty = MR_YES;
+    } else {
+        IsEmpty = MR_NO;
+    }
+").
+
+:- pragma foreign_proc("C",
+    contains_point(Region::in, X::in, Y::in, Result::out, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    if (cairo_region_contains_point(Region->mcairo_raw_region, (int)X, (int)Y))
+    {
+        Result = MR_YES;
+    } else {
+        Result = MR_NO;
+    }
+").
+
+contains_rectangle(Region, Rectangle, Overlap, !IO) :-
+    Rectangle = rectangle(X, Y, Width, Height),
+    contains_rectangle_2(Region, X, Y, Width, Height, Overlap, !IO).
+
+:- pred contains_rectangle_2(region::in, int::in, int::in, int::in, int::in,
+    overlap::out, io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+    contains_rectangle_2(Region::in, X::in, Y::in, W::in, H::in,
+        Overlap::out, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_rectangle_int_t   r;
+
+    r.x = X;
+    r.y = Y;
+    r.width = W;
+    r.height = H;
+
+    Overlap = cairo_region_contains_rectangle(Region->mcairo_raw_region, &r);
+
+").
+
+:- pragma foreign_proc("C",
+    equal(A::in, B::in, Result::out, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    if (cairo_region_equal(A->mcairo_raw_region, B->mcairo_raw_region)) {
+        Result = MR_YES;
+    } else {
+        Result = MR_NO;
+    }
+").
+
+:- pragma foreign_proc("C",
+    translate(Region::in, Dx::in, Dy::in, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_region_translate(Region->mcairo_raw_region, Dx, Dy);
+").
+
+:- pragma foreign_proc("C",
+    intersect(Dst::in, Other::in, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_region_intersect(Dst->mcairo_raw_region,
+        Other->mcairo_raw_region);
+").
+
+intersect_rectangle(Region, Rectangle, !IO) :-
+    Rectangle = rectangle(X, Y, Width, Height),
+    intersect_rectangle_2(Region, X, Y, Width, Height, !IO).
+
+:- pred intersect_rectangle_2(region::in, int::in, int::in, int::in, int::in,
+     io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+    intersect_rectangle_2(Region::in, X::in, Y::in, W::in, H::in,
+        _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_rectangle_int_t   rectangle;
+ 
+    rectangle.x = X;
+    rectangle.y = Y;
+    rectangle.width = W;
+    rectangle.height = H;
+    cairo_region_intersect_rectangle(Region->mcairo_raw_region,
+        &rectangle);
+").
+
+:- pragma foreign_proc("C",
+    subtract(Dst::in, Other::in, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_region_subtract(Dst->mcairo_raw_region,
+        Other->mcairo_raw_region);
+").
+
+subtract_rectangle(Region, Rectangle, !IO) :-
+    Rectangle = rectangle(X, Y, Width, Height),
+    subtract_rectangle_2(Region, X, Y, Width, Height, !IO).
+
+:- pred subtract_rectangle_2(region::in, int::in, int::in, int::in, int::in,
+     io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+    subtract_rectangle_2(Region::in, X::in, Y::in, W::in, H::in,
+        _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_rectangle_int_t   rectangle;
+ 
+    rectangle.x = X;
+    rectangle.y = Y;
+    rectangle.width = W;
+    rectangle.height = H;
+    cairo_region_subtract_rectangle(Region->mcairo_raw_region,
+        &rectangle);
+").
+
+:- pragma foreign_proc("C",
+    union(Dst::in, Other::in, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_region_union(Dst->mcairo_raw_region,
+        Other->mcairo_raw_region);
+").
+
+union_rectangle(Region, Rectangle, !IO) :-
+    Rectangle = rectangle(X, Y, Width, Height),
+    union_rectangle_2(Region, X, Y, Width, Height, !IO).
+
+:- pred union_rectangle_2(region::in, int::in, int::in, int::in, int::in,
+     io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+    union_rectangle_2(Region::in, X::in, Y::in, W::in, H::in,
+        _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_rectangle_int_t   rectangle;
+ 
+    rectangle.x = X;
+    rectangle.y = Y;
+    rectangle.width = W;
+    rectangle.height = H;
+    cairo_region_union_rectangle(Region->mcairo_raw_region,
+        &rectangle);
+").
+
+:- pragma foreign_proc("C",
+    xor(Dst::in, Other::in, _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_region_xor(Dst->mcairo_raw_region,
+        Other->mcairo_raw_region);
+").
+
+xor_rectangle(Region, Rectangle, !IO) :-
+    Rectangle = rectangle(X, Y, Width, Height),
+    xor_rectangle_2(Region, X, Y, Width, Height, !IO).
+
+:- pred xor_rectangle_2(region::in, int::in, int::in, int::in, int::in,
+     io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+    xor_rectangle_2(Region::in, X::in, Y::in, W::in, H::in,
+        _IO0::di, _IO::uo),
+    [promise_pure, will_not_call_mercury, tabled_for_io],
+"
+    cairo_rectangle_int_t   rectangle;
+ 
+    rectangle.x = X;
+    rectangle.y = Y;
+    rectangle.width = W;
+    rectangle.height = H;
+    cairo_region_xor_rectangle(Region->mcairo_raw_region,
+        &rectangle);
+").
+
+%-----------------------------------------------------------------------------%
+:- end_module cairo.region.
+%-----------------------------------------------------------------------------%

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list