mupdf
Loading...
Searching...
No Matches
geometry.h
Go to the documentation of this file.
1// Copyright (C) 2004-2025 Artifex Software, Inc.
2//
3// This file is part of MuPDF.
4//
5// MuPDF is free software: you can redistribute it and/or modify it under the
6// terms of the GNU Affero General Public License as published by the Free
7// Software Foundation, either version 3 of the License, or (at your option)
8// any later version.
9//
10// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13// details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17//
18// Alternative licensing terms are available from the licensor.
19// For commercial licensing, see <https://www.artifex.com/> or contact
20// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21// CA 94129, USA, for further information.
22
23#ifndef MUPDF_FITZ_MATH_H
24#define MUPDF_FITZ_MATH_H
25
26#include "mupdf/fitz/system.h"
27
28#include <math.h>
29#include <assert.h>
30
31#ifndef M_PI
32#define M_PI 3.14159265358979323846
33#endif
34
38static inline int fz_mul255(int a, int b)
39{
40 /* see Jim Blinn's book "Dirty Pixels" for how this works */
41 int x = a * b + 128;
42 x += x >> 8;
43 return x >> 8;
44}
45
49static inline int fz_div255(int c, int a)
50{
51 return a ? c * (255 * 256 / a) >> 8 : 0;
52}
53
57#define FZ_EXPAND(A) ((A)+((A)>>7))
58
63#define FZ_COMBINE(A,B) (((A)*(B))>>8)
64
70#define FZ_COMBINE2(A,B,C,D) (((A) * (B) + (C) * (D))>>8)
71
76#define FZ_BLEND(SRC, DST, AMOUNT) ((((SRC)-(DST))*(AMOUNT) + ((DST)<<8))>>8)
77
81float fz_atof(const char *s);
82
86int fz_atoi(const char *s);
87
91int64_t fz_atoi64(const char *s);
92
99size_t fz_atoz(const char *s);
100
106static inline float fz_abs(float f)
107{
108 return (f < 0 ? -f : f);
109}
110
111static inline int fz_absi(int i)
112{
113 return (i < 0 ? -i : i);
114}
115
116static inline float fz_min(float a, float b)
117{
118 return (a < b ? a : b);
119}
120
121static inline int fz_mini(int a, int b)
122{
123 return (a < b ? a : b);
124}
125
126static inline size_t fz_minz(size_t a, size_t b)
127{
128 return (a < b ? a : b);
129}
130
131static inline int64_t fz_mini64(int64_t a, int64_t b)
132{
133 return (a < b ? a : b);
134}
135
136static inline float fz_max(float a, float b)
137{
138 return (a > b ? a : b);
139}
140
141static inline int fz_maxi(int a, int b)
142{
143 return (a > b ? a : b);
144}
145
146static inline size_t fz_maxz(size_t a, size_t b)
147{
148 return (a > b ? a : b);
149}
150
151static inline int64_t fz_maxi64(int64_t a, int64_t b)
152{
153 return (a > b ? a : b);
154}
155
156static inline float fz_clamp(float x, float min, float max)
157{
158 return x < min ? min : x > max ? max : x;
159}
160
161static inline int fz_clampi(int x, int min, int max)
162{
163 return x < min ? min : x > max ? max : x;
164}
165
166static inline int64_t fz_clamp64(int64_t x, int64_t min, int64_t max)
167{
168 return x < min ? min : x > max ? max : x;
169}
170
171static inline double fz_clampd(double x, double min, double max)
172{
173 return x < min ? min : x > max ? max : x;
174}
175
176static inline void *fz_clampp(void *x, void *min, void *max)
177{
178 return x < min ? min : x > max ? max : x;
179}
180
181#define DIV_BY_ZERO(a, b, min, max) (((a) < 0) ^ ((b) < 0) ? (min) : (max))
182
186typedef struct
187{
188 float x, y;
189} fz_point;
190
191static inline fz_point fz_make_point(float x, float y)
192{
193 fz_point p = { x, y };
194 return p;
195}
196
227#define FZ_MIN_INF_RECT ((int)0x80000000)
228#define FZ_MAX_INF_RECT ((int)0x7fffff80)
229
230typedef struct
231{
232 float x0, y0;
233 float x1, y1;
234} fz_rect;
235
236static inline fz_rect fz_make_rect(float x0, float y0, float x1, float y1)
237{
238 fz_rect r = { x0, y0, x1, y1 };
239 return r;
240}
241
247typedef struct
248{
249 int x0, y0;
250 int x1, y1;
251} fz_irect;
252
253static inline fz_irect fz_make_irect(int x0, int y0, int x1, int y1)
254{
255 fz_irect r = { x0, y0, x1, y1 };
256 return r;
257}
258
265FZ_DATA extern const fz_rect fz_unit_rect;
266
270FZ_DATA extern const fz_rect fz_empty_rect;
271FZ_DATA extern const fz_irect fz_empty_irect;
272
276FZ_DATA extern const fz_rect fz_infinite_rect;
278
282FZ_DATA extern const fz_rect fz_invalid_rect;
284
291static inline int fz_is_empty_rect(fz_rect r)
292{
293 return (r.x0 >= r.x1 || r.y0 >= r.y1);
294}
295
296static inline int fz_is_empty_irect(fz_irect r)
297{
298 return (r.x0 >= r.x1 || r.y0 >= r.y1);
299}
300
304static inline int fz_is_infinite_rect(fz_rect r)
305{
306 return (r.x0 == FZ_MIN_INF_RECT && r.x1 == FZ_MAX_INF_RECT &&
307 r.y0 == FZ_MIN_INF_RECT && r.y1 == FZ_MAX_INF_RECT);
308}
309
314static inline int fz_is_infinite_irect(fz_irect r)
315{
316 return (r.x0 == FZ_MIN_INF_RECT && r.x1 == FZ_MAX_INF_RECT &&
317 r.y0 == FZ_MIN_INF_RECT && r.y1 == FZ_MAX_INF_RECT);
318}
319
323static inline int fz_is_valid_rect(fz_rect r)
324{
325 return (r.x0 <= r.x1 && r.y0 <= r.y1);
326}
327
331static inline int fz_is_valid_irect(fz_irect r)
332{
333 return (r.x0 <= r.x1 && r.y0 <= r.y1);
334}
335
339static inline unsigned int
340fz_irect_width(fz_irect r)
341{
342 unsigned int w;
343 if (r.x0 >= r.x1)
344 return 0;
345 /* Check for w overflowing. This should never happen, but
346 * if it does, it's pretty likely an indication of a severe
347 * problem. */
348 w = (unsigned int)r.x1 - r.x0;
349 assert((int)w >= 0);
350 if ((int)w < 0)
351 return 0;
352 return (int)w;
353}
354
358static inline int
359fz_irect_height(fz_irect r)
360{
361 unsigned int h;
362 if (r.y0 >= r.y1)
363 return 0;
364 /* Check for h overflowing. This should never happen, but
365 * if it does, it's pretty likely an indication of a severe
366 * problem. */
367 h = (unsigned int)(r.y1 - r.y0);
368 assert((int)h >= 0);
369 if ((int)h < 0)
370 return 0;
371 return (int)h;
372}
373
387typedef struct
388{
389 float a, b, c, d, e, f;
390} fz_matrix;
391
395FZ_DATA extern const fz_matrix fz_identity;
396
397static inline fz_matrix fz_make_matrix(float a, float b, float c, float d, float e, float f)
398{
399 fz_matrix m = { a, b, c, d, e, f };
400 return m;
401}
402
403static inline int fz_is_identity(fz_matrix m)
404{
405 return m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && m.e == 0 && m.f == 0;
406}
407
417
431fz_matrix fz_scale(float sx, float sy);
432
444fz_matrix fz_pre_scale(fz_matrix m, float sx, float sy);
445
457fz_matrix fz_post_scale(fz_matrix m, float sx, float sy);
458
471fz_matrix fz_shear(float sx, float sy);
472
485fz_matrix fz_pre_shear(fz_matrix m, float sx, float sy);
486
500fz_matrix fz_rotate(float degrees);
501
516
530fz_matrix fz_translate(float tx, float ty);
531
543fz_matrix fz_pre_translate(fz_matrix m, float tx, float ty);
544
551fz_matrix fz_transform_page(fz_rect mediabox, float resolution, float rotate);
552
563
575
585
590
603
611
623
634
650
664
670
677
685
691fz_rect fz_translate_rect(fz_rect a, float xoff, float yoff);
692fz_irect fz_translate_irect(fz_irect a, int xoff, int yoff);
693
700
708
722
733
750
755
768
774
781typedef struct
782{
784} fz_quad;
785
789static inline fz_quad fz_make_quad(
790 float ul_x, float ul_y,
791 float ur_x, float ur_y,
792 float ll_x, float ll_y,
793 float lr_x, float lr_y)
794{
795 fz_quad q = {
796 { ul_x, ul_y },
797 { ur_x, ur_y },
798 { ll_x, ll_y },
799 { lr_x, lr_y },
800 };
801 return q;
802}
803
804FZ_DATA extern const fz_quad fz_invalid_quad;
805FZ_DATA extern const fz_quad fz_infinite_quad;
806
811
816
821
826
831
836
841
847
853
865
877
884
891
892/* Checked integer arithmetic helpers -- return whether operation succeeded without overflow or underflow. */
893/* Use builtin C23 ckd_mul, ckd_add, ckd_sub if available. */
894
895#ifdef HAVE_STDCKDINT_H
896
897#include <stdckdint.h>
898
899/* We add explicit casts here to ensure that these match the non-C23 cases below. */
900#define fz_ckd_mul_i32(O,A,B) ckd_mul(O,(int32_t)(A),(int32_t)(B))
901#define fz_ckd_mul_u32(O,A,B) ckd_mul(O,(uint32_t)(A),(uint32_t)(B))
902#define fz_ckd_mul_int(O,A,B) ckd_mul(O,(int)(A),(int)(B))
903#define fz_ckd_mul_uint(O,A,B) ckd_mul(O,(unsigned int)(A),(unsigned int)(B))
904#define fz_ckd_mul_size(O,A,B) ckd_mul(O,(size_t)(A),(size_t)(B))
905#define fz_ckd_mul_i64(O,A,B) ckd_mul(O,(int64_t)(A),(int64_t)(B))
906#define fz_ckd_mul_u64(O,A,B) ckd_mul(O,(uint64_t)(A),(uint64_t)(B))
907
908#define fz_ckd_add_i32(O,A,B) ckd_add(O,(int32_t)(A),(int32_t)(B))
909#define fz_ckd_add_u32(O,A,B) ckd_add(O,(uint32_t)(A),(uint32_t)(B))
910#define fz_ckd_add_int(O,A,B) ckd_add(O,(int)(A),(int)(B))
911#define fz_ckd_add_uint(O,A,B) ckd_add(O,(unsigned int)(A),(unsigned int)(B))
912#define fz_ckd_add_size(O,A,B) ckd_add(O,(size_t)(A),(size_t)(B))
913#define fz_ckd_add_i64(O,A,B) ckd_add(O,(int64_t)(A),(int64_t)(B))
914#define fz_ckd_add_u64(O,A,B) ckd_add(O,(uint64_t)(A),(uint64_t)(B))
915
916#define fz_ckd_sub_i32(O,A,B) ckd_sub(O,(int32_t)(A),(int32_t)(B))
917#define fz_ckd_sub_u32(O,A,B) ckd_sub(O,(uint32_t)(A),(uint32_t)(B))
918#define fz_ckd_sub_int(O,A,B) ckd_sub(O,(int)(A),(int)(B))
919#define fz_ckd_sub_uint(O,A,B) ckd_sub(O,(unsigned int)(A),(unsigned int)(B))
920#define fz_ckd_sub_size(O,A,B) ckd_sub(O,(size_t)(A),(size_t)(B))
921#define fz_ckd_sub_i64(O,A,B) ckd_sub(O,(int64_t)(A),(int64_t)(B))
922#define fz_ckd_sub_u64(O,A,B) ckd_sub(O,(uint64_t)(A),(uint64_t)(B))
923
924#else
925
926int fz_ckd_mul_i32(int32_t *out, int32_t a, int32_t b);
927int fz_ckd_add_i32(int32_t *out, int32_t a, int32_t b);
928int fz_ckd_sub_i32(int32_t *out, int32_t a, int32_t b);
929
930int fz_ckd_mul_u32(uint32_t *out, uint32_t a, uint32_t b);
931int fz_ckd_add_u32(uint32_t *out, uint32_t a, uint32_t b);
932int fz_ckd_sub_u32(uint32_t *out, uint32_t a, uint32_t b);
933
934int fz_ckd_mul_int(int *out, int a, int b);
935int fz_ckd_add_int(int *out, int a, int b);
936int fz_ckd_sub_int(int *out, int a, int b);
937
938int fz_ckd_mul_uint(unsigned int *out, unsigned int a, unsigned int b);
939int fz_ckd_add_uint(unsigned int *out, unsigned int a, unsigned int b);
940int fz_ckd_sub_uint(unsigned int *out, unsigned int a, unsigned int b);
941
942int fz_ckd_mul_size(size_t *out, size_t a, size_t b);
943int fz_ckd_add_size(size_t *out, size_t a, size_t b);
944int fz_ckd_sub_size(size_t *out, size_t a, size_t b);
945
946int fz_ckd_mul_i64(int64_t *out, int64_t a, int64_t b);
947int fz_ckd_add_i64(int64_t *out, int64_t a, int64_t b);
948int fz_ckd_sub_i64(int64_t *out, int64_t a, int64_t b);
949
950int fz_ckd_mul_u64(uint64_t *out, uint64_t a, uint64_t b);
951int fz_ckd_add_u64(uint64_t *out, uint64_t a, uint64_t b);
952int fz_ckd_sub_u64(uint64_t *out, uint64_t a, uint64_t b);
953
954#endif
955
956#define fz_bytes_from_bits(A) (((A)>>3) + !!((A) & 7))
957
958int fz_ckd_size_from_i64(size_t *out, int64_t in);
959int fz_ckd_int_from_i64(int *out, int64_t in);
960
961#endif
#define FZ_DATA
Definition export.h:49
fz_rect fz_intersect_rect(fz_rect a, fz_rect b)
int fz_is_infinite_quad(fz_quad q)
FZ_DATA const fz_quad fz_infinite_quad
float fz_matrix_max_expansion(fz_matrix m)
int fz_ckd_sub_i32(int32_t *out, int32_t a, int32_t b)
int fz_contains_rect(fz_rect a, fz_rect b)
fz_rect fz_include_point_in_rect(fz_rect r, fz_point p)
int fz_ckd_add_i64(int64_t *out, int64_t a, int64_t b)
fz_matrix fz_pre_scale(fz_matrix m, float sx, float sy)
fz_rect fz_expand_rect(fz_rect b, float expand)
int64_t fz_atoi64(const char *s)
int fz_is_point_inside_rect(fz_point p, fz_rect r)
int fz_ckd_sub_uint(unsigned int *out, unsigned int a, unsigned int b)
int fz_ckd_int_from_i64(int *out, int64_t in)
#define FZ_MAX_INF_RECT
Definition geometry.h:228
int fz_ckd_mul_size(size_t *out, size_t a, size_t b)
int fz_ckd_add_u64(uint64_t *out, uint64_t a, uint64_t b)
int fz_ckd_sub_u64(uint64_t *out, uint64_t a, uint64_t b)
int fz_is_irect_inside_irect(fz_irect inner, fz_irect outer)
int fz_ckd_sub_size(size_t *out, size_t a, size_t b)
int fz_is_empty_quad(fz_quad q)
fz_matrix fz_shear(float sx, float sy)
fz_point fz_transform_vector(fz_point vector, fz_matrix m)
fz_irect fz_translate_irect(fz_irect a, int xoff, int yoff)
int fz_atoi(const char *s)
fz_matrix fz_post_scale(fz_matrix m, float sx, float sy)
int fz_is_point_inside_quad(fz_point p, fz_quad q)
int fz_ckd_add_int(int *out, int a, int b)
float fz_matrix_expansion(fz_matrix m)
int fz_is_point_inside_irect(int x, int y, fz_irect r)
fz_irect fz_intersect_irect(fz_irect a, fz_irect b)
fz_rect fz_union_rect(fz_rect a, fz_rect b)
int fz_overlaps_rect(fz_rect a, fz_rect b)
fz_matrix fz_pre_rotate(fz_matrix m, float degrees)
FZ_DATA const fz_rect fz_empty_rect
fz_matrix fz_gridfit_matrix(int as_tiled, fz_matrix m)
fz_rect fz_translate_rect(fz_rect a, float xoff, float yoff)
fz_rect fz_rect_from_irect(fz_irect bbox)
#define FZ_MIN_INF_RECT
Definition geometry.h:227
fz_point fz_normalize_vector(fz_point p)
size_t fz_atoz(const char *s)
int fz_ckd_add_i32(int32_t *out, int32_t a, int32_t b)
fz_irect fz_round_rect(fz_rect rect)
FZ_DATA const fz_matrix fz_identity
int fz_ckd_mul_i64(int64_t *out, int64_t a, int64_t b)
fz_irect fz_expand_irect(fz_irect a, int expand)
int fz_ckd_size_from_i64(size_t *out, int64_t in)
int fz_ckd_mul_u64(uint64_t *out, uint64_t a, uint64_t b)
fz_matrix fz_pre_shear(fz_matrix m, float sx, float sy)
int fz_ckd_add_u32(uint32_t *out, uint32_t a, uint32_t b)
int fz_ckd_mul_uint(unsigned int *out, unsigned int a, unsigned int b)
FZ_DATA const fz_rect fz_unit_rect
fz_rect fz_rect_from_quad(fz_quad q)
int fz_is_quad_inside_quad(fz_quad needle, fz_quad haystack)
float fz_rect_area(fz_rect r)
fz_matrix fz_invert_matrix(fz_matrix matrix)
int fz_is_rect_inside_rect(fz_rect inner, fz_rect outer)
fz_matrix fz_pre_translate(fz_matrix m, float tx, float ty)
FZ_DATA const fz_irect fz_infinite_irect
fz_point fz_transform_point_xy(float x, float y, fz_matrix m)
FZ_DATA const fz_irect fz_empty_irect
int fz_ckd_mul_int(int *out, int a, int b)
int fz_is_valid_quad(fz_quad q)
fz_point fz_transform_point(fz_point point, fz_matrix m)
int fz_ckd_add_size(size_t *out, size_t a, size_t b)
int fz_ckd_mul_i32(int32_t *out, int32_t a, int32_t b)
fz_matrix fz_scale(float sx, float sy)
fz_quad fz_transform_quad(fz_quad q, fz_matrix m)
fz_matrix fz_transform_page(fz_rect mediabox, float resolution, float rotate)
int fz_ckd_mul_u32(uint32_t *out, uint32_t a, uint32_t b)
int fz_is_rectilinear(fz_matrix m)
FZ_DATA const fz_quad fz_invalid_quad
fz_matrix fz_rotate(float degrees)
int fz_ckd_sub_int(int *out, int a, int b)
fz_matrix fz_concat(fz_matrix left, fz_matrix right)
int fz_ckd_sub_i64(int64_t *out, int64_t a, int64_t b)
int fz_ckd_add_uint(unsigned int *out, unsigned int a, unsigned int b)
float fz_atof(const char *s)
fz_matrix fz_translate(float tx, float ty)
FZ_DATA const fz_rect fz_infinite_rect
FZ_DATA const fz_irect fz_invalid_irect
int fz_ckd_sub_u32(uint32_t *out, uint32_t a, uint32_t b)
fz_quad fz_quad_from_rect(fz_rect r)
int fz_is_quad_intersecting_quad(fz_quad a, fz_quad b)
int fz_try_invert_matrix(fz_matrix *inv, fz_matrix src)
fz_rect fz_transform_rect(fz_rect rect, fz_matrix m)
fz_irect fz_irect_from_rect(fz_rect rect)
FZ_DATA const fz_rect fz_invalid_rect
Definition geometry.h:248
int y1
Definition geometry.h:250
int y0
Definition geometry.h:249
int x1
Definition geometry.h:250
int x0
Definition geometry.h:249
Definition geometry.h:388
float e
Definition geometry.h:389
float f
Definition geometry.h:389
float d
Definition geometry.h:389
float a
Definition geometry.h:389
float c
Definition geometry.h:389
float b
Definition geometry.h:389
Definition geometry.h:187
float x
Definition geometry.h:188
float y
Definition geometry.h:188
Definition geometry.h:782
fz_point ul
Definition geometry.h:783
fz_point ll
Definition geometry.h:783
fz_point lr
Definition geometry.h:783
fz_point ur
Definition geometry.h:783
Definition geometry.h:231
float y0
Definition geometry.h:232
float x0
Definition geometry.h:232
float y1
Definition geometry.h:233
float x1
Definition geometry.h:233