diff mupdf-source/include/mupdf/fitz/geometry.h @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/include/mupdf/fitz/geometry.h	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,877 @@
+// Copyright (C) 2004-2025 Artifex Software, Inc.
+//
+// This file is part of MuPDF.
+//
+// MuPDF is free software: you can redistribute it and/or modify it under the
+// terms of the GNU Affero General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option)
+// any later version.
+//
+// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
+//
+// Alternative licensing terms are available from the licensor.
+// For commercial licensing, see <https://www.artifex.com/> or contact
+// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
+// CA 94129, USA, for further information.
+
+#ifndef MUPDF_FITZ_MATH_H
+#define MUPDF_FITZ_MATH_H
+
+#include "mupdf/fitz/system.h"
+
+#include <math.h>
+#include <assert.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+/**
+	Multiply scaled two integers in the 0..255 range
+*/
+static inline int fz_mul255(int a, int b)
+{
+	/* see Jim Blinn's book "Dirty Pixels" for how this works */
+	int x = a * b + 128;
+	x += x >> 8;
+	return x >> 8;
+}
+
+/**
+	Undo alpha premultiplication.
+*/
+static inline int fz_div255(int c, int a)
+{
+	return a ? c * (255 * 256 / a) >> 8 : 0;
+}
+
+/**
+	Expand a value A from the 0...255 range to the 0..256 range
+*/
+#define FZ_EXPAND(A) ((A)+((A)>>7))
+
+/**
+	Combine values A (in any range) and B (in the 0..256 range),
+	to give a single value in the same range as A was.
+*/
+#define FZ_COMBINE(A,B) (((A)*(B))>>8)
+
+/**
+	Combine values A and C (in the same (any) range) and B and D (in
+	the 0..256 range), to give a single value in the same range as A
+	and C were.
+*/
+#define FZ_COMBINE2(A,B,C,D) (((A) * (B) + (C) * (D))>>8)
+
+/**
+	Blend SRC and DST (in the same range) together according to
+	AMOUNT (in the 0...256 range).
+*/
+#define FZ_BLEND(SRC, DST, AMOUNT) ((((SRC)-(DST))*(AMOUNT) + ((DST)<<8))>>8)
+
+/**
+	Range checking atof
+*/
+float fz_atof(const char *s);
+
+/**
+	atoi that copes with NULL
+*/
+int fz_atoi(const char *s);
+
+/**
+	64bit atoi that copes with NULL
+*/
+int64_t fz_atoi64(const char *s);
+
+/**
+	size_t atoi that copes with NULL.
+
+	NOTE: limited to 63bits. Negative numbers
+	are returned as 0.
+*/
+size_t fz_atoz(const char *s);
+
+/**
+	Some standard math functions, done as static inlines for speed.
+	People with compilers that do not adequately implement inline
+	may like to reimplement these using macros.
+*/
+static inline float fz_abs(float f)
+{
+	return (f < 0 ? -f : f);
+}
+
+static inline int fz_absi(int i)
+{
+	return (i < 0 ? -i : i);
+}
+
+static inline float fz_min(float a, float b)
+{
+	return (a < b ? a : b);
+}
+
+static inline int fz_mini(int a, int b)
+{
+	return (a < b ? a : b);
+}
+
+static inline size_t fz_minz(size_t a, size_t b)
+{
+	return (a < b ? a : b);
+}
+
+static inline int64_t fz_mini64(int64_t a, int64_t b)
+{
+	return (a < b ? a : b);
+}
+
+static inline float fz_max(float a, float b)
+{
+	return (a > b ? a : b);
+}
+
+static inline int fz_maxi(int a, int b)
+{
+	return (a > b ? a : b);
+}
+
+static inline size_t fz_maxz(size_t a, size_t b)
+{
+	return (a > b ? a : b);
+}
+
+static inline int64_t fz_maxi64(int64_t a, int64_t b)
+{
+	return (a > b ? a : b);
+}
+
+static inline float fz_clamp(float x, float min, float max)
+{
+	return x < min ? min : x > max ? max : x;
+}
+
+static inline int fz_clampi(int x, int min, int max)
+{
+	return x < min ? min : x > max ? max : x;
+}
+
+static inline int64_t fz_clamp64(int64_t x, int64_t min, int64_t max)
+{
+	return x < min ? min : x > max ? max : x;
+}
+
+static inline double fz_clampd(double x, double min, double max)
+{
+	return x < min ? min : x > max ? max : x;
+}
+
+static inline void *fz_clampp(void *x, void *min, void *max)
+{
+	return x < min ? min : x > max ? max : x;
+}
+
+#define DIV_BY_ZERO(a, b, min, max) (((a) < 0) ^ ((b) < 0) ? (min) : (max))
+
+/**
+	fz_point is a point in a two-dimensional space.
+*/
+typedef struct
+{
+	float x, y;
+} fz_point;
+
+static inline fz_point fz_make_point(float x, float y)
+{
+	fz_point p = { x, y };
+	return p;
+}
+
+/**
+	fz_rect is a rectangle represented by two diagonally opposite
+	corners at arbitrary coordinates.
+
+	Rectangles are always axis-aligned with the X- and Y- axes. We
+	wish to distinguish rectangles in 3 categories; infinite, finite,
+	and invalid. Zero area rectangles are a sub-category of finite
+	ones.
+
+	For all valid rectangles, x0 <= x1 and y0 <= y1 in all cases.
+	Infinite rectangles have x0 = y0 = FZ_MIN_INF_RECT,
+	x1 = y1 = FZ_MAX_INF_RECT. For any non infinite valid rectangle,
+	the area is defined as (x1 - x0) * (y1 - y0).
+
+	To check for empty or infinite rectangles use fz_is_empty_rect
+	and fz_is_infinite_rect. To check for valid rectangles use
+	fz_is_valid_rect.
+
+	We choose this representation, so that we can easily distinguish
+	the difference between intersecting 2 valid rectangles and
+	getting an invalid one, as opposed to getting a zero area one
+	(which nonetheless has valid bounds within the plane).
+
+	x0, y0: The top left corner.
+
+	x1, y1: The bottom right corner.
+
+	We choose FZ_{MIN,MAX}_INF_RECT to be the largest 32bit signed
+	integer values that survive roundtripping to floats.
+*/
+#define FZ_MIN_INF_RECT ((int)0x80000000)
+#define FZ_MAX_INF_RECT ((int)0x7fffff80)
+
+typedef struct
+{
+	float x0, y0;
+	float x1, y1;
+} fz_rect;
+
+static inline fz_rect fz_make_rect(float x0, float y0, float x1, float y1)
+{
+	fz_rect r = { x0, y0, x1, y1 };
+	return r;
+}
+
+/**
+	fz_irect is a rectangle using integers instead of floats.
+
+	It's used in the draw device and for pixmap dimensions.
+*/
+typedef struct
+{
+	int x0, y0;
+	int x1, y1;
+} fz_irect;
+
+static inline fz_irect fz_make_irect(int x0, int y0, int x1, int y1)
+{
+	fz_irect r = { x0, y0, x1, y1 };
+	return r;
+}
+
+/**
+	A rectangle with sides of length one.
+
+	The bottom left corner is at (0, 0) and the top right corner
+	is at (1, 1).
+*/
+FZ_DATA extern const fz_rect fz_unit_rect;
+
+/**
+	An empty rectangle with an area equal to zero.
+*/
+FZ_DATA extern const fz_rect fz_empty_rect;
+FZ_DATA extern const fz_irect fz_empty_irect;
+
+/**
+	An infinite rectangle.
+*/
+FZ_DATA extern const fz_rect fz_infinite_rect;
+FZ_DATA extern const fz_irect fz_infinite_irect;
+
+/**
+	An invalid rectangle.
+*/
+FZ_DATA extern const fz_rect fz_invalid_rect;
+FZ_DATA extern const fz_irect fz_invalid_irect;
+
+/**
+	Check if rectangle is empty.
+
+	An empty rectangle is defined as one whose area is zero.
+	All invalid rectangles are empty.
+*/
+static inline int fz_is_empty_rect(fz_rect r)
+{
+	return (r.x0 >= r.x1 || r.y0 >= r.y1);
+}
+
+static inline int fz_is_empty_irect(fz_irect r)
+{
+	return (r.x0 >= r.x1 || r.y0 >= r.y1);
+}
+
+/**
+	Check if rectangle is infinite.
+*/
+static inline int fz_is_infinite_rect(fz_rect r)
+{
+	return (r.x0 == FZ_MIN_INF_RECT && r.x1 == FZ_MAX_INF_RECT &&
+		r.y0 == FZ_MIN_INF_RECT && r.y1 == FZ_MAX_INF_RECT);
+}
+
+/**
+	Check if an integer rectangle
+	is infinite.
+*/
+static inline int fz_is_infinite_irect(fz_irect r)
+{
+	return (r.x0 == FZ_MIN_INF_RECT && r.x1 == FZ_MAX_INF_RECT &&
+		r.y0 == FZ_MIN_INF_RECT && r.y1 == FZ_MAX_INF_RECT);
+}
+
+/**
+	Check if rectangle is valid.
+*/
+static inline int fz_is_valid_rect(fz_rect r)
+{
+	return (r.x0 <= r.x1 && r.y0 <= r.y1);
+}
+
+/**
+	Check if an integer rectangle is valid.
+*/
+static inline int fz_is_valid_irect(fz_irect r)
+{
+	return (r.x0 <= r.x1 && r.y0 <= r.y1);
+}
+
+/**
+	Return the width of an irect. Invalid irects return 0.
+*/
+static inline unsigned int
+fz_irect_width(fz_irect r)
+{
+	unsigned int w;
+	if (r.x0 >= r.x1)
+		return 0;
+	/* Check for w overflowing. This should never happen, but
+	 * if it does, it's pretty likely an indication of a severe
+	 * problem. */
+	w = (unsigned int)r.x1 - r.x0;
+	assert((int)w >= 0);
+	if ((int)w < 0)
+		return 0;
+	return (int)w;
+}
+
+/**
+	Return the height of an irect. Invalid irects return 0.
+*/
+static inline int
+fz_irect_height(fz_irect r)
+{
+	unsigned int h;
+	if (r.y0 >= r.y1)
+		return 0;
+	/* Check for h overflowing. This should never happen, but
+	 * if it does, it's pretty likely an indication of a severe
+	 * problem. */
+	h = (unsigned int)(r.y1 - r.y0);
+	assert((int)h >= 0);
+	if ((int)h < 0)
+		return 0;
+	return (int)h;
+}
+
+/**
+	fz_matrix is a row-major 3x3 matrix used for representing
+	transformations of coordinates throughout MuPDF.
+
+	Since all points reside in a two-dimensional space, one vector
+	is always a constant unit vector; hence only some elements may
+	vary in a matrix. Below is how the elements map between
+	different representations.
+
+	/ a b 0 \
+	| c d 0 | normally represented as [ a b c d e f ].
+	\ e f 1 /
+*/
+typedef struct
+{
+	float a, b, c, d, e, f;
+} fz_matrix;
+
+/**
+	Identity transform matrix.
+*/
+FZ_DATA extern const fz_matrix fz_identity;
+
+static inline fz_matrix fz_make_matrix(float a, float b, float c, float d, float e, float f)
+{
+	fz_matrix m = { a, b, c, d, e, f };
+	return m;
+}
+
+static inline int fz_is_identity(fz_matrix m)
+{
+	return m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && m.e == 0 && m.f == 0;
+}
+
+/**
+	Multiply two matrices.
+
+	The order of the two matrices are important since matrix
+	multiplication is not commutative.
+
+	Returns result.
+*/
+fz_matrix fz_concat(fz_matrix left, fz_matrix right);
+
+/**
+	Create a scaling matrix.
+
+	The returned matrix is of the form [ sx 0 0 sy 0 0 ].
+
+	m: Pointer to the matrix to populate
+
+	sx, sy: Scaling factors along the X- and Y-axes. A scaling
+	factor of 1.0 will not cause any scaling along the relevant
+	axis.
+
+	Returns m.
+*/
+fz_matrix fz_scale(float sx, float sy);
+
+/**
+	Scale a matrix by premultiplication.
+
+	m: Pointer to the matrix to scale
+
+	sx, sy: Scaling factors along the X- and Y-axes. A scaling
+	factor of 1.0 will not cause any scaling along the relevant
+	axis.
+
+	Returns m (updated).
+*/
+fz_matrix fz_pre_scale(fz_matrix m, float sx, float sy);
+
+/**
+	Scale a matrix by postmultiplication.
+
+	m: Pointer to the matrix to scale
+
+	sx, sy: Scaling factors along the X- and Y-axes. A scaling
+	factor of 1.0 will not cause any scaling along the relevant
+	axis.
+
+	Returns m (updated).
+*/
+fz_matrix fz_post_scale(fz_matrix m, float sx, float sy);
+
+/**
+	Create a shearing matrix.
+
+	The returned matrix is of the form [ 1 sy sx 1 0 0 ].
+
+	m: pointer to place to store returned matrix
+
+	sx, sy: Shearing factors. A shearing factor of 0.0 will not
+	cause any shearing along the relevant axis.
+
+	Returns m.
+*/
+fz_matrix fz_shear(float sx, float sy);
+
+/**
+	Premultiply a matrix with a shearing matrix.
+
+	The shearing matrix is of the form [ 1 sy sx 1 0 0 ].
+
+	m: pointer to matrix to premultiply
+
+	sx, sy: Shearing factors. A shearing factor of 0.0 will not
+	cause any shearing along the relevant axis.
+
+	Returns m (updated).
+*/
+fz_matrix fz_pre_shear(fz_matrix m, float sx, float sy);
+
+/**
+	Create a rotation matrix.
+
+	The returned matrix is of the form
+	[ cos(deg) sin(deg) -sin(deg) cos(deg) 0 0 ].
+
+	m: Pointer to place to store matrix
+
+	degrees: Degrees of counter clockwise rotation. Values less
+	than zero and greater than 360 are handled as expected.
+
+	Returns m.
+*/
+fz_matrix fz_rotate(float degrees);
+
+/**
+	Rotate a transformation by premultiplying.
+
+	The premultiplied matrix is of the form
+	[ cos(deg) sin(deg) -sin(deg) cos(deg) 0 0 ].
+
+	m: Pointer to matrix to premultiply.
+
+	degrees: Degrees of counter clockwise rotation. Values less
+	than zero and greater than 360 are handled as expected.
+
+	Returns m (updated).
+*/
+fz_matrix fz_pre_rotate(fz_matrix m, float degrees);
+
+/**
+	Create a translation matrix.
+
+	The returned matrix is of the form [ 1 0 0 1 tx ty ].
+
+	m: A place to store the created matrix.
+
+	tx, ty: Translation distances along the X- and Y-axes. A
+	translation of 0 will not cause any translation along the
+	relevant axis.
+
+	Returns m.
+*/
+fz_matrix fz_translate(float tx, float ty);
+
+/**
+	Translate a matrix by premultiplication.
+
+	m: The matrix to translate
+
+	tx, ty: Translation distances along the X- and Y-axes. A
+	translation of 0 will not cause any translation along the
+	relevant axis.
+
+	Returns m.
+*/
+fz_matrix fz_pre_translate(fz_matrix m, float tx, float ty);
+
+/**
+	Create transform matrix to draw page
+	at a given resolution and rotation. Adjusts the scaling
+	factors so that the page covers whole number of
+	pixels and adjust the page origin to be at 0,0.
+*/
+fz_matrix fz_transform_page(fz_rect mediabox, float resolution, float rotate);
+
+/**
+	Create an inverse matrix.
+
+	matrix: Matrix to invert. A degenerate matrix, where the
+	determinant is equal to zero, can not be inverted and the
+	original matrix is returned instead.
+
+	Returns inverse.
+*/
+fz_matrix fz_invert_matrix(fz_matrix matrix);
+
+/**
+	Attempt to create an inverse matrix.
+
+	inv: Place to store inverse matrix.
+
+	src: Matrix to invert. A degenerate matrix, where the
+	determinant is equal to zero, can not be inverted.
+
+	Returns 1 if matrix is degenerate (singular), or 0 otherwise.
+*/
+int fz_try_invert_matrix(fz_matrix *inv, fz_matrix src);
+
+/**
+	Check if a transformation is rectilinear.
+
+	Rectilinear means that no shearing is present and that any
+	rotations present are a multiple of 90 degrees. Usually this
+	is used to make sure that axis-aligned rectangles before the
+	transformation are still axis-aligned rectangles afterwards.
+*/
+int fz_is_rectilinear(fz_matrix m);
+
+/**
+	Calculate average scaling factor of matrix.
+*/
+float fz_matrix_expansion(fz_matrix m);
+
+/**
+	Compute intersection of two rectangles.
+
+	Given two rectangles, update the first to be the smallest
+	axis-aligned rectangle that covers the area covered by both
+	given rectangles. If either rectangle is empty then the
+	intersection is also empty. If either rectangle is infinite
+	then the intersection is simply the non-infinite rectangle.
+	Should both rectangles be infinite, then the intersection is
+	also infinite.
+*/
+fz_rect fz_intersect_rect(fz_rect a, fz_rect b);
+
+/**
+	Compute intersection of two bounding boxes.
+
+	Similar to fz_intersect_rect but operates on two bounding
+	boxes instead of two rectangles.
+*/
+fz_irect fz_intersect_irect(fz_irect a, fz_irect b);
+
+/**
+	Compute union of two rectangles.
+
+	Given two rectangles, update the first to be the smallest
+	axis-aligned rectangle that encompasses both given rectangles.
+	If either rectangle is infinite then the union is also infinite.
+	If either rectangle is empty then the union is simply the
+	non-empty rectangle. Should both rectangles be empty, then the
+	union is also empty.
+*/
+fz_rect fz_union_rect(fz_rect a, fz_rect b);
+
+/**
+	Convert a rect into the minimal bounding box
+	that covers the rectangle.
+
+	Coordinates in a bounding box are integers, so rounding of the
+	rects coordinates takes place. The top left corner is rounded
+	upwards and left while the bottom right corner is rounded
+	downwards and to the right.
+*/
+fz_irect fz_irect_from_rect(fz_rect rect);
+
+/**
+	Round rectangle coordinates.
+
+	Coordinates in a bounding box are integers, so rounding of the
+	rects coordinates takes place. The top left corner is rounded
+	upwards and left while the bottom right corner is rounded
+	downwards and to the right.
+
+	This differs from fz_irect_from_rect, in that fz_irect_from_rect
+	slavishly follows the numbers (i.e any slight over/under
+	calculations can cause whole extra pixels to be added).
+	fz_round_rect allows for a small amount of rounding error when
+	calculating the bbox.
+*/
+fz_irect fz_round_rect(fz_rect rect);
+
+/**
+	Convert a bbox into a rect.
+
+	For our purposes, a rect can represent all the values we meet in
+	a bbox, so nothing can go wrong.
+
+	rect: A place to store the generated rectangle.
+
+	bbox: The bbox to convert.
+
+	Returns rect (updated).
+*/
+fz_rect fz_rect_from_irect(fz_irect bbox);
+
+/**
+	Expand a bbox by a given amount in all directions.
+*/
+fz_rect fz_expand_rect(fz_rect b, float expand);
+fz_irect fz_expand_irect(fz_irect a, int expand);
+
+/**
+	Expand a bbox to include a given point.
+	To create a rectangle that encompasses a sequence of points, the
+	rectangle must first be set to be the empty rectangle at one of
+	the points before including the others.
+*/
+fz_rect fz_include_point_in_rect(fz_rect r, fz_point p);
+
+/**
+	Translate bounding box.
+
+	Translate a bbox by a given x and y offset. Allows for overflow.
+*/
+fz_rect fz_translate_rect(fz_rect a, float xoff, float yoff);
+fz_irect fz_translate_irect(fz_irect a, int xoff, int yoff);
+
+/**
+	Test rectangle inclusion.
+
+	Return true if a entirely contains b.
+*/
+int fz_contains_rect(fz_rect a, fz_rect b);
+
+/**
+	Apply a transformation to a point.
+
+	transform: Transformation matrix to apply. See fz_concat,
+	fz_scale, fz_rotate and fz_translate for how to create a
+	matrix.
+
+	point: Pointer to point to update.
+
+	Returns transform (unchanged).
+*/
+fz_point fz_transform_point(fz_point point, fz_matrix m);
+fz_point fz_transform_point_xy(float x, float y, fz_matrix m);
+
+/**
+	Apply a transformation to a vector.
+
+	transform: Transformation matrix to apply. See fz_concat,
+	fz_scale and fz_rotate for how to create a matrix. Any
+	translation will be ignored.
+
+	vector: Pointer to vector to update.
+*/
+fz_point fz_transform_vector(fz_point vector, fz_matrix m);
+
+/**
+	Apply a transform to a rectangle.
+
+	After the four corner points of the axis-aligned rectangle
+	have been transformed it may not longer be axis-aligned. So a
+	new axis-aligned rectangle is created covering at least the
+	area of the transformed rectangle.
+
+	transform: Transformation matrix to apply. See fz_concat,
+	fz_scale and fz_rotate for how to create a matrix.
+
+	rect: Rectangle to be transformed. The two special cases
+	fz_empty_rect and fz_infinite_rect, may be used but are
+	returned unchanged as expected.
+*/
+fz_rect fz_transform_rect(fz_rect rect, fz_matrix m);
+
+/**
+	Normalize a vector to length one.
+*/
+fz_point fz_normalize_vector(fz_point p);
+
+/**
+	Grid fit a matrix.
+
+	as_tiled = 0 => adjust the matrix so that the image of the unit
+	square completely covers any pixel that was touched by the
+	image of the unit square under the original matrix.
+
+	as_tiled = 1 => adjust the matrix so that the corners of the
+	image of the unit square align with the closest integer corner
+	of the image of the unit square under the original matrix.
+*/
+fz_matrix fz_gridfit_matrix(int as_tiled, fz_matrix m);
+
+/**
+	Find the largest expansion performed by this matrix.
+	(i.e. max(abs(m.a),abs(m.b),abs(m.c),abs(m.d))
+*/
+float fz_matrix_max_expansion(fz_matrix m);
+
+/**
+	A representation for a region defined by 4 points.
+
+	The significant difference between quads and rects is that
+	the edges of quads are not axis aligned.
+*/
+typedef struct
+{
+	fz_point ul, ur, ll, lr;
+} fz_quad;
+
+/**
+	Inline convenience construction function.
+*/
+static inline fz_quad fz_make_quad(
+	float ul_x, float ul_y,
+	float ur_x, float ur_y,
+	float ll_x, float ll_y,
+	float lr_x, float lr_y)
+{
+	fz_quad q = {
+		{ ul_x, ul_y },
+		{ ur_x, ur_y },
+		{ ll_x, ll_y },
+		{ lr_x, lr_y },
+	};
+	return q;
+}
+
+FZ_DATA extern const fz_quad fz_invalid_quad;
+FZ_DATA extern const fz_quad fz_infinite_quad;
+
+/**
+	Is a quad valid?
+*/
+int fz_is_valid_quad(fz_quad q);
+
+/**
+	Is a quad empty?
+*/
+int fz_is_empty_quad(fz_quad q);
+
+/**
+	Is a quad infinite?
+*/
+int fz_is_infinite_quad(fz_quad q);
+
+/**
+	Convert a rect to a quad (losslessly).
+*/
+fz_quad fz_quad_from_rect(fz_rect r);
+
+/**
+	Convert a quad to the smallest rect that covers it.
+*/
+fz_rect fz_rect_from_quad(fz_quad q);
+
+/**
+	Transform a quad by a matrix.
+*/
+fz_quad fz_transform_quad(fz_quad q, fz_matrix m);
+
+/**
+	Inclusion test for quads.
+*/
+int fz_is_point_inside_quad(fz_point p, fz_quad q);
+
+/**
+	Inclusion test for rects. (Rect is assumed to be open, i.e.
+	top right corner is not included).
+*/
+int fz_is_point_inside_rect(fz_point p, fz_rect r);
+
+/**
+	Inclusion test for irects. (Rect is assumed to be open, i.e.
+	top right corner is not included).
+*/
+int fz_is_point_inside_irect(int x, int y, fz_irect r);
+
+/**
+	Inclusion test for rects.
+
+	rects are assumed to be both open or both closed.
+
+	No invalid rect can include any other rect.
+	No invalid rect can be included by any rect.
+	Empty (point) rects can include themselves.
+	Empty (line) rects can include many (subline) rects.
+*/
+int fz_is_rect_inside_rect(fz_rect inner, fz_rect outer);
+
+/**
+	Inclusion test for irects.
+
+	rects are assumed to be both open or both closed.
+
+	No invalid rect can include any other rect.
+	No invalid rect can be included by any rect.
+	Empty (point) rects can include themselves.
+	Empty (line) rects can include many (subline) rects.
+*/
+int fz_is_irect_inside_irect(fz_irect inner, fz_irect outer);
+
+/**
+	Inclusion test for quad in quad.
+
+	This may break down if quads are not 'well formed'.
+*/
+int fz_is_quad_inside_quad(fz_quad needle, fz_quad haystack);
+
+/**
+	Intersection test for quads.
+
+	This may break down if quads are not 'well formed'.
+*/
+int fz_is_quad_intersecting_quad(fz_quad a, fz_quad b);
+
+#endif