init commit
Some checks failed
Test / test (1.22.x, macos-latest) (push) Has been cancelled
Test / test (1.22.x, ubuntu-latest) (push) Has been cancelled

This commit is contained in:
landaiqing
2026-02-10 14:45:18 +08:00
parent a530a79566
commit 5ce88674da
142 changed files with 12394 additions and 4280 deletions

View File

@@ -1,9 +1,33 @@
// Copyright (C) 2004-2022 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 <assert.h>
/**
Multiply scaled two integers in the 0..255 range
*/
static inline int fz_mul255(int a, int b)
@@ -14,45 +38,57 @@ static inline int fz_mul255(int a, int b)
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);
/*
/**
Some standard math functions, done as static inlines for speed.
People with compilers that do not adequately implement inlines may
like to reimplement these using macros.
People with compilers that do not adequately implement inline
may like to reimplement these using macros.
*/
static inline float fz_abs(float f)
{
@@ -79,6 +115,11 @@ 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);
@@ -89,41 +130,50 @@ 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 f, float min, float max)
static inline float fz_clamp(float x, float min, float max)
{
return (f > min ? (f < max ? f : max) : min);
return x < min ? min : x > max ? max : x;
}
static inline int fz_clampi(int i, int min, int max)
static inline int fz_clampi(int x, int min, int max)
{
return (i > min ? (i < max ? i : max) : min);
return x < min ? min : x > max ? max : x;
}
static inline double fz_clampd(double d, double min, double max)
static inline int64_t fz_clamp64(int64_t x, int64_t min, int64_t max)
{
return (d > min ? (d < max ? d : max) : min);
return x < min ? min : x > max ? max : x;
}
static inline void *fz_clampp(void *p, void *min, void *max)
static inline double fz_clampd(double x, double min, double max)
{
return (p > min ? (p < max ? p : max) : min);
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 fz_point_s fz_point;
struct fz_point_s
typedef struct
{
float x, y;
};
} fz_point;
static inline fz_point fz_make_point(float x, float y)
{
@@ -131,30 +181,44 @@ static inline fz_point fz_make_point(float x, float 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.
The relationship between the coordinates are that x0 <= x1 and
y0 <= y1 in all cases except for infinite rectangles. The area
of a rectangle is defined as (x1 - x0) * (y1 - y0). If either
x0 > x1 or y0 > y1 is true for a given rectangle then it is
defined to be infinite.
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.
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.
*/
typedef struct fz_rect_s fz_rect;
struct fz_rect_s
#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)
{
@@ -162,33 +226,16 @@ static inline fz_rect fz_make_rect(float x0, float y0, float x1, float y1)
return r;
}
/*
fz_rect_min: get the minimum point from a rectangle as a fz_point.
*/
static inline fz_point *fz_rect_min(fz_rect *f)
{
return (fz_point *)&f->x0;
}
/*
fz_rect_max: get the maximum point from a rectangle as a fz_point.
*/
static inline fz_point *fz_rect_max(fz_rect *f)
{
return (fz_point *)&f->x1;
}
/*
/**
fz_irect is a rectangle using integers instead of floats.
It's used in the draw device and for pixmap dimensions.
*/
typedef struct fz_irect_s fz_irect;
struct fz_irect_s
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)
{
@@ -196,74 +243,116 @@ static inline fz_irect fz_make_irect(int x0, int y0, int x1, int 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).
*/
extern const fz_rect fz_unit_rect;
FZ_DATA extern const fz_rect fz_unit_rect;
/*
/**
An empty rectangle with an area equal to zero.
Both the top left and bottom right corner are at (0, 0).
*/
extern const fz_rect fz_empty_rect;
extern const fz_irect fz_empty_irect;
FZ_DATA extern const fz_rect fz_empty_rect;
FZ_DATA extern const fz_irect fz_empty_irect;
/*
An infinite rectangle with negative area.
The corner (x0, y0) is at (1, 1) while the corner (x1, y1) is
at (-1, -1).
/**
An infinite rectangle.
*/
extern const fz_rect fz_infinite_rect;
extern const fz_irect fz_infinite_irect;
FZ_DATA extern const fz_rect fz_infinite_rect;
FZ_DATA extern const fz_irect fz_infinite_irect;
/*
fz_is_empty_rect: Check if rectangle is empty.
/**
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(const fz_rect *r)
static inline int fz_is_empty_rect(fz_rect r)
{
return ((r)->x0 == (r)->x1 || (r)->y0 == (r)->y1);
return (r.x0 >= r.x1 || r.y0 >= r.y1);
}
static inline int
fz_is_empty_irect(const fz_irect *r)
static inline int fz_is_empty_irect(fz_irect r)
{
return ((r)->x0 == (r)->x1 || (r)->y0 == (r)->y1);
return (r.x0 >= r.x1 || r.y0 >= r.y1);
}
/*
fz_is_infinite_rect: Check if rectangle is infinite.
An infinite rectangle is defined as one where either of the
two relationships between corner coordinates are not true.
/**
Check if rectangle is infinite.
*/
static inline int
fz_is_infinite_rect(const fz_rect *r)
static inline int fz_is_infinite_rect(fz_rect r)
{
return ((r)->x0 > (r)->x1 || (r)->y0 > (r)->y1);
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);
}
/*
fz_is_infinite_irect: Check if an integer rectangle
/**
Check if an integer rectangle
is infinite.
An infinite rectangle is defined as one where either of the
two relationships between corner coordinates are not true.
*/
static inline int
fz_is_infinite_irect(const fz_irect *r)
static inline int fz_is_infinite_irect(fz_irect r)
{
return ((r)->x0 > (r)->x1 || (r)->y0 > (r)->y1);
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.
@@ -276,16 +365,15 @@ fz_is_infinite_irect(const fz_irect *r)
| c d 0 | normally represented as [ a b c d e f ].
\ e f 1 /
*/
typedef struct fz_matrix_s fz_matrix;
struct fz_matrix_s
typedef struct
{
float a, b, c, d, e, f;
};
} fz_matrix;
/*
fz_identity: Identity transform matrix.
/**
Identity transform matrix.
*/
extern const fz_matrix fz_identity;
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)
{
@@ -293,24 +381,23 @@ static inline fz_matrix fz_make_matrix(float a, float b, float c, float d, float
return m;
}
static inline fz_matrix *fz_copy_matrix(fz_matrix *restrict m, const fz_matrix *restrict s)
static inline int fz_is_identity(fz_matrix m)
{
*m = *s;
return m;
return m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && m.e == 0 && m.f == 0;
}
/*
fz_concat: Multiply two matrices.
/**
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 *result, const fz_matrix *left, const fz_matrix *right);
fz_matrix fz_concat(fz_matrix left, fz_matrix right);
/*
fz_scale: Create a scaling matrix.
/**
Create a scaling matrix.
The returned matrix is of the form [ sx 0 0 sy 0 0 ].
@@ -322,10 +409,10 @@ fz_matrix *fz_concat(fz_matrix *result, const fz_matrix *left, const fz_matrix *
Returns m.
*/
fz_matrix *fz_scale(fz_matrix *m, float sx, float sy);
fz_matrix fz_scale(float sx, float sy);
/*
fz_pre_scale: Scale a matrix by premultiplication.
/**
Scale a matrix by premultiplication.
m: Pointer to the matrix to scale
@@ -335,10 +422,10 @@ fz_matrix *fz_scale(fz_matrix *m, float sx, float sy);
Returns m (updated).
*/
fz_matrix *fz_pre_scale(fz_matrix *m, float sx, float sy);
fz_matrix fz_pre_scale(fz_matrix m, float sx, float sy);
/*
fz_post_scale: Scale a matrix by postmultiplication.
/**
Scale a matrix by postmultiplication.
m: Pointer to the matrix to scale
@@ -348,10 +435,10 @@ fz_matrix *fz_pre_scale(fz_matrix *m, float sx, float sy);
Returns m (updated).
*/
fz_matrix *fz_post_scale(fz_matrix *m, float sx, float sy);
fz_matrix fz_post_scale(fz_matrix m, float sx, float sy);
/*
fz_shear: Create a shearing matrix.
/**
Create a shearing matrix.
The returned matrix is of the form [ 1 sy sx 1 0 0 ].
@@ -362,10 +449,10 @@ fz_matrix *fz_post_scale(fz_matrix *m, float sx, float sy);
Returns m.
*/
fz_matrix *fz_shear(fz_matrix *m, float sx, float sy);
fz_matrix fz_shear(float sx, float sy);
/*
fz_pre_shear: Premultiply a matrix with a shearing matrix.
/**
Premultiply a matrix with a shearing matrix.
The shearing matrix is of the form [ 1 sy sx 1 0 0 ].
@@ -376,10 +463,10 @@ fz_matrix *fz_shear(fz_matrix *m, float sx, float sy);
Returns m (updated).
*/
fz_matrix *fz_pre_shear(fz_matrix *m, float sx, float sy);
fz_matrix fz_pre_shear(fz_matrix m, float sx, float sy);
/*
fz_rotate: Create a rotation matrix.
/**
Create a rotation matrix.
The returned matrix is of the form
[ cos(deg) sin(deg) -sin(deg) cos(deg) 0 0 ].
@@ -391,10 +478,10 @@ fz_matrix *fz_pre_shear(fz_matrix *m, float sx, float sy);
Returns m.
*/
fz_matrix *fz_rotate(fz_matrix *m, float degrees);
fz_matrix fz_rotate(float degrees);
/*
fz_pre_rotate: Rotate a transformation by premultiplying.
/**
Rotate a transformation by premultiplying.
The premultiplied matrix is of the form
[ cos(deg) sin(deg) -sin(deg) cos(deg) 0 0 ].
@@ -406,10 +493,10 @@ fz_matrix *fz_rotate(fz_matrix *m, float degrees);
Returns m (updated).
*/
fz_matrix *fz_pre_rotate(fz_matrix *m, float degrees);
fz_matrix fz_pre_rotate(fz_matrix m, float degrees);
/*
fz_translate: Create a translation matrix.
/**
Create a translation matrix.
The returned matrix is of the form [ 1 0 0 1 tx ty ].
@@ -421,10 +508,10 @@ fz_matrix *fz_pre_rotate(fz_matrix *m, float degrees);
Returns m.
*/
fz_matrix *fz_translate(fz_matrix *m, float tx, float ty);
fz_matrix fz_translate(float tx, float ty);
/*
fz_pre_translate: Translate a matrix by premultiplication.
/**
Translate a matrix by premultiplication.
m: The matrix to translate
@@ -434,10 +521,18 @@ fz_matrix *fz_translate(fz_matrix *m, float tx, float ty);
Returns m.
*/
fz_matrix *fz_pre_translate(fz_matrix *m, float tx, float ty);
fz_matrix fz_pre_translate(fz_matrix m, float tx, float ty);
/*
fz_invert_matrix: Create an inverse matrix.
/**
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.
inverse: Place to store inverse matrix.
@@ -447,10 +542,10 @@ fz_matrix *fz_pre_translate(fz_matrix *m, float tx, float ty);
Returns inverse.
*/
fz_matrix *fz_invert_matrix(fz_matrix *inverse, const fz_matrix *matrix);
fz_matrix fz_invert_matrix(fz_matrix matrix);
/*
fz_try_invert_matrix: Attempt to create an inverse matrix.
/**
Attempt to create an inverse matrix.
inverse: Place to store inverse matrix.
@@ -459,25 +554,25 @@ fz_matrix *fz_invert_matrix(fz_matrix *inverse, const fz_matrix *matrix);
Returns 1 if matrix is degenerate (singular), or 0 otherwise.
*/
int fz_try_invert_matrix(fz_matrix *inverse, const fz_matrix *matrix);
int fz_try_invert_matrix(fz_matrix *inv, fz_matrix src);
/*
fz_is_rectilinear: Check if a transformation is rectilinear.
/**
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(const fz_matrix *m);
int fz_is_rectilinear(fz_matrix m);
/*
fz_matrix_expansion: Calculate average scaling factor of matrix.
/**
Calculate average scaling factor of matrix.
*/
float fz_matrix_expansion(const fz_matrix *m); /* sumatrapdf */
float fz_matrix_expansion(fz_matrix m);
/*
fz_intersect_rect: Compute intersection of two rectangles.
/**
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
@@ -487,18 +582,18 @@ float fz_matrix_expansion(const fz_matrix *m); /* sumatrapdf */
Should both rectangles be infinite, then the intersection is
also infinite.
*/
fz_rect *fz_intersect_rect(fz_rect *restrict a, const fz_rect *restrict b);
fz_rect fz_intersect_rect(fz_rect a, fz_rect b);
/*
fz_intersect_irect: Compute intersection of two bounding boxes.
/**
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 *restrict a, const fz_irect *restrict b);
fz_irect fz_intersect_irect(fz_irect a, fz_irect b);
/*
fz_union_rect: Compute union of two rectangles.
/**
Compute union of two rectangles.
Given two rectangles, update the first to be the smallest
axis-aligned rectangle that encompasses both given rectangles.
@@ -507,28 +602,21 @@ fz_irect *fz_intersect_irect(fz_irect *restrict a, const fz_irect *restrict b);
non-empty rectangle. Should both rectangles be empty, then the
union is also empty.
*/
fz_rect *fz_union_rect(fz_rect *restrict a, const fz_rect *restrict b);
fz_rect fz_union_rect(fz_rect a, fz_rect b);
/*
fz_irect_from_rect: Convert a rect into the minimal bounding box
/**
Convert a rect into the minimal bounding box
that covers the rectangle.
bbox: Place to store the returned bbox.
rect: The rectangle to convert to a bbox.
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.
Returns bbox (updated).
*/
fz_irect fz_irect_from_rect(fz_rect rect);
fz_irect *fz_irect_from_rect(fz_irect *restrict bbox, const fz_rect *restrict rect);
/*
fz_round_rect: Round rectangle coordinates.
/**
Round rectangle coordinates.
Coordinates in a bounding box are integers, so rounding of the
rects coordinates takes place. The top left corner is rounded
@@ -536,15 +624,15 @@ fz_irect *fz_irect_from_rect(fz_irect *restrict bbox, const fz_rect *restrict re
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.
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_irect *restrict bbox, const fz_rect *restrict rect);
fz_irect fz_round_rect(fz_rect rect);
/*
fz_rect_from_irect: Convert a bbox into a 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.
@@ -555,39 +643,39 @@ fz_irect *fz_round_rect(fz_irect *restrict bbox, const fz_rect *restrict rect);
Returns rect (updated).
*/
fz_rect *fz_rect_from_irect(fz_rect *restrict rect, const fz_irect *restrict bbox);
fz_rect fz_rect_from_irect(fz_irect bbox);
/*
fz_expand_rect: Expand a bbox by a given amount in all directions.
/**
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);
fz_rect fz_expand_rect(fz_rect b, float expand);
fz_irect fz_expand_irect(fz_irect a, int expand);
/*
fz_include_point_in_rect: Expand a bbox to include a given point.
/**
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, const fz_point *p);
fz_rect fz_include_point_in_rect(fz_rect r, fz_point p);
/*
fz_translate_irect: Translate bounding box.
/**
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);
fz_rect fz_translate_rect(fz_rect a, float xoff, float yoff);
fz_irect fz_translate_irect(fz_irect a, int xoff, int yoff);
/*
fz_contains_rect: Test rectangle inclusion.
/**
Test rectangle inclusion.
Return true if a entirely contains b.
*/
int fz_contains_rect(const fz_rect *a, const fz_rect *b);
int fz_contains_rect(fz_rect a, fz_rect b);
/*
fz_transform_point: Apply a transformation to a point.
/**
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
@@ -597,11 +685,11 @@ int fz_contains_rect(const fz_rect *a, const fz_rect *b);
Returns transform (unchanged).
*/
fz_point *fz_transform_point(fz_point *restrict point, const fz_matrix *restrict transform);
fz_point *fz_transform_point_xy(fz_point *restrict point, const fz_matrix *restrict transform, float x, float y);
fz_point fz_transform_point(fz_point point, fz_matrix m);
fz_point fz_transform_point_xy(float x, float y, fz_matrix m);
/*
fz_transform_vector: Apply a transformation to a vector.
/**
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
@@ -609,10 +697,10 @@ fz_point *fz_transform_point_xy(fz_point *restrict point, const fz_matrix *restr
vector: Pointer to vector to update.
*/
fz_point *fz_transform_vector(fz_point *restrict vector, const fz_matrix *restrict transform);
fz_point fz_transform_vector(fz_point vector, fz_matrix m);
/*
fz_transform_rect: Apply a transform to a rectangle.
/**
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
@@ -626,15 +714,105 @@ fz_point *fz_transform_vector(fz_point *restrict vector, const fz_matrix *restri
fz_empty_rect and fz_infinite_rect, may be used but are
returned unchanged as expected.
*/
fz_rect *fz_transform_rect(fz_rect *restrict rect, const fz_matrix *restrict transform);
fz_rect fz_transform_rect(fz_rect rect, fz_matrix m);
/*
fz_normalize_vector: Normalize a vector to length one.
/**
Normalize a vector to length one.
*/
void fz_normalize_vector(fz_point *p);
fz_point fz_normalize_vector(fz_point p);
void fz_gridfit_matrix(int as_tiled, fz_matrix *m);
/**
Grid fit a matrix.
float fz_matrix_max_expansion(const fz_matrix *m);
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;
}
/**
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 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