Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7858 views
1
#ifndef MUPDF_FITZ_MATH_H
2
#define MUPDF_FITZ_MATH_H
3
4
#include "mupdf/fitz/system.h"
5
6
/* Multiply scaled two integers in the 0..255 range */
7
static inline int fz_mul255(int a, int b)
8
{
9
/* see Jim Blinn's book "Dirty Pixels" for how this works */
10
int x = a * b + 128;
11
x += x >> 8;
12
return x >> 8;
13
}
14
15
/* Expand a value A from the 0...255 range to the 0..256 range */
16
#define FZ_EXPAND(A) ((A)+((A)>>7))
17
18
/* Combine values A (in any range) and B (in the 0..256 range),
19
* to give a single value in the same range as A was. */
20
#define FZ_COMBINE(A,B) (((A)*(B))>>8)
21
22
/* Combine values A and C (in the same (any) range) and B and D (in the
23
* 0..256 range), to give a single value in the same range as A and C were. */
24
#define FZ_COMBINE2(A,B,C,D) (FZ_COMBINE((A), (B)) + FZ_COMBINE((C), (D)))
25
26
/* Blend SRC and DST (in the same range) together according to
27
* AMOUNT (in the 0...256 range). */
28
#define FZ_BLEND(SRC, DST, AMOUNT) ((((SRC)-(DST))*(AMOUNT) + ((DST)<<8))>>8)
29
30
/* Range checking atof */
31
float fz_atof(const char *s);
32
33
/* atoi that copes with NULL */
34
int fz_atoi(const char *s);
35
36
/*
37
Some standard math functions, done as static inlines for speed.
38
People with compilers that do not adequately implement inlines may
39
like to reimplement these using macros.
40
*/
41
static inline float fz_abs(float f)
42
{
43
return (f < 0 ? -f : f);
44
}
45
46
static inline int fz_absi(int i)
47
{
48
return (i < 0 ? -i : i);
49
}
50
51
static inline float fz_min(float a, float b)
52
{
53
return (a < b ? a : b);
54
}
55
56
static inline int fz_mini(int a, int b)
57
{
58
return (a < b ? a : b);
59
}
60
61
static inline float fz_max(float a, float b)
62
{
63
return (a > b ? a : b);
64
}
65
66
static inline int fz_maxi(int a, int b)
67
{
68
return (a > b ? a : b);
69
}
70
71
static inline float fz_clamp(float f, float min, float max)
72
{
73
return (f > min ? (f < max ? f : max) : min);
74
}
75
76
static inline int fz_clampi(int i, int min, int max)
77
{
78
return (i > min ? (i < max ? i : max) : min);
79
}
80
81
static inline double fz_clampd(double d, double min, double max)
82
{
83
return (d > min ? (d < max ? d : max) : min);
84
}
85
86
static inline void *fz_clampp(void *p, void *min, void *max)
87
{
88
return (p > min ? (p < max ? p : max) : min);
89
}
90
91
#define DIV_BY_ZERO(a, b, min, max) (((a) < 0) ^ ((b) < 0) ? (min) : (max))
92
93
/*
94
fz_point is a point in a two-dimensional space.
95
*/
96
typedef struct fz_point_s fz_point;
97
struct fz_point_s
98
{
99
float x, y;
100
};
101
102
/*
103
fz_rect is a rectangle represented by two diagonally opposite
104
corners at arbitrary coordinates.
105
106
Rectangles are always axis-aligned with the X- and Y- axes.
107
The relationship between the coordinates are that x0 <= x1 and
108
y0 <= y1 in all cases except for infinte rectangles. The area
109
of a rectangle is defined as (x1 - x0) * (y1 - y0). If either
110
x0 > x1 or y0 > y1 is true for a given rectangle then it is
111
defined to be infinite.
112
113
To check for empty or infinite rectangles use fz_is_empty_rect
114
and fz_is_infinite_rect.
115
116
x0, y0: The top left corner.
117
118
x1, y1: The botton right corner.
119
*/
120
typedef struct fz_rect_s fz_rect;
121
struct fz_rect_s
122
{
123
float x0, y0;
124
float x1, y1;
125
};
126
127
/*
128
fz_rect_min: get the minimum point from a rectangle as an fz_point.
129
*/
130
static inline fz_point *fz_rect_min(fz_rect *f)
131
{
132
return (fz_point *)&f->x0;
133
}
134
135
/*
136
fz_rect_max: get the maximum point from a rectangle as an fz_point.
137
*/
138
static inline fz_point *fz_rect_max(fz_rect *f)
139
{
140
return (fz_point *)&f->x1;
141
}
142
143
/*
144
fz_irect is a rectangle using integers instead of floats.
145
146
It's used in the draw device and for pixmap dimensions.
147
*/
148
typedef struct fz_irect_s fz_irect;
149
struct fz_irect_s
150
{
151
int x0, y0;
152
int x1, y1;
153
};
154
155
/*
156
A rectangle with sides of length one.
157
158
The bottom left corner is at (0, 0) and the top right corner
159
is at (1, 1).
160
*/
161
extern const fz_rect fz_unit_rect;
162
163
/*
164
An empty rectangle with an area equal to zero.
165
166
Both the top left and bottom right corner are at (0, 0).
167
*/
168
extern const fz_rect fz_empty_rect;
169
extern const fz_irect fz_empty_irect;
170
171
/*
172
An infinite rectangle with negative area.
173
174
The corner (x0, y0) is at (1, 1) while the corner (x1, y1) is
175
at (-1, -1).
176
*/
177
extern const fz_rect fz_infinite_rect;
178
extern const fz_irect fz_infinite_irect;
179
180
/*
181
fz_is_empty_rect: Check if rectangle is empty.
182
183
An empty rectangle is defined as one whose area is zero.
184
*/
185
static inline int
186
fz_is_empty_rect(const fz_rect *r)
187
{
188
return ((r)->x0 == (r)->x1 || (r)->y0 == (r)->y1);
189
}
190
191
static inline int
192
fz_is_empty_irect(const fz_irect *r)
193
{
194
return ((r)->x0 == (r)->x1 || (r)->y0 == (r)->y1);
195
}
196
197
/*
198
fz_is_infinite: Check if rectangle is infinite.
199
200
An infinite rectangle is defined as one where either of the
201
two relationships between corner coordinates are not true.
202
*/
203
static inline int
204
fz_is_infinite_rect(const fz_rect *r)
205
{
206
return ((r)->x0 > (r)->x1 || (r)->y0 > (r)->y1);
207
}
208
209
static inline int
210
fz_is_infinite_irect(const fz_irect *r)
211
{
212
return ((r)->x0 > (r)->x1 || (r)->y0 > (r)->y1);
213
}
214
215
/*
216
fz_matrix is a a row-major 3x3 matrix used for representing
217
transformations of coordinates throughout MuPDF.
218
219
Since all points reside in a two-dimensional space, one vector
220
is always a constant unit vector; hence only some elements may
221
vary in a matrix. Below is how the elements map between
222
different representations.
223
224
/ a b 0 \
225
| c d 0 | normally represented as [ a b c d e f ].
226
\ e f 1 /
227
*/
228
typedef struct fz_matrix_s fz_matrix;
229
struct fz_matrix_s
230
{
231
float a, b, c, d, e, f;
232
};
233
234
/*
235
fz_identity: Identity transform matrix.
236
*/
237
extern const fz_matrix fz_identity;
238
239
static inline fz_matrix *fz_copy_matrix(fz_matrix *restrict m, const fz_matrix *restrict s)
240
{
241
*m = *s;
242
return m;
243
}
244
245
/*
246
fz_concat: Multiply two matrices.
247
248
The order of the two matrices are important since matrix
249
multiplication is not commutative.
250
251
Returns result.
252
253
Does not throw exceptions.
254
*/
255
fz_matrix *fz_concat(fz_matrix *result, const fz_matrix *left, const fz_matrix *right);
256
257
/*
258
fz_scale: Create a scaling matrix.
259
260
The returned matrix is of the form [ sx 0 0 sy 0 0 ].
261
262
m: Pointer to the matrix to populate
263
264
sx, sy: Scaling factors along the X- and Y-axes. A scaling
265
factor of 1.0 will not cause any scaling along the relevant
266
axis.
267
268
Returns m.
269
270
Does not throw exceptions.
271
*/
272
fz_matrix *fz_scale(fz_matrix *m, float sx, float sy);
273
274
/*
275
fz_pre_scale: Scale a matrix by premultiplication.
276
277
m: Pointer to the matrix to scale
278
279
sx, sy: Scaling factors along the X- and Y-axes. A scaling
280
factor of 1.0 will not cause any scaling along the relevant
281
axis.
282
283
Returns m (updated).
284
285
Does not throw exceptions.
286
*/
287
fz_matrix *fz_pre_scale(fz_matrix *m, float sx, float sy);
288
289
/*
290
fz_shear: Create a shearing matrix.
291
292
The returned matrix is of the form [ 1 sy sx 1 0 0 ].
293
294
m: pointer to place to store returned matrix
295
296
sx, sy: Shearing factors. A shearing factor of 0.0 will not
297
cause any shearing along the relevant axis.
298
299
Returns m.
300
301
Does not throw exceptions.
302
*/
303
fz_matrix *fz_shear(fz_matrix *m, float sx, float sy);
304
305
/*
306
fz_pre_shear: Premultiply a matrix with a shearing matrix.
307
308
The shearing matrix is of the form [ 1 sy sx 1 0 0 ].
309
310
m: pointer to matrix to premultiply
311
312
sx, sy: Shearing factors. A shearing factor of 0.0 will not
313
cause any shearing along the relevant axis.
314
315
Returns m (updated).
316
317
Does not throw exceptions.
318
*/
319
fz_matrix *fz_pre_shear(fz_matrix *m, float sx, float sy);
320
321
/*
322
fz_rotate: Create a rotation matrix.
323
324
The returned matrix is of the form
325
[ cos(deg) sin(deg) -sin(deg) cos(deg) 0 0 ].
326
327
m: Pointer to place to store matrix
328
329
degrees: Degrees of counter clockwise rotation. Values less
330
than zero and greater than 360 are handled as expected.
331
332
Returns m.
333
334
Does not throw exceptions.
335
*/
336
fz_matrix *fz_rotate(fz_matrix *m, float degrees);
337
338
/*
339
fz_pre_rotate: Rotate a transformation by premultiplying.
340
341
The premultiplied matrix is of the form
342
[ cos(deg) sin(deg) -sin(deg) cos(deg) 0 0 ].
343
344
m: Pointer to matrix to premultiply.
345
346
degrees: Degrees of counter clockwise rotation. Values less
347
than zero and greater than 360 are handled as expected.
348
349
Returns m (updated).
350
351
Does not throw exceptions.
352
*/
353
fz_matrix *fz_pre_rotate(fz_matrix *m, float degrees);
354
355
/*
356
fz_translate: Create a translation matrix.
357
358
The returned matrix is of the form [ 1 0 0 1 tx ty ].
359
360
m: A place to store the created matrix.
361
362
tx, ty: Translation distances along the X- and Y-axes. A
363
translation of 0 will not cause any translation along the
364
relevant axis.
365
366
Returns m.
367
368
Does not throw exceptions.
369
*/
370
fz_matrix *fz_translate(fz_matrix *m, float tx, float ty);
371
372
/*
373
fz_pre_translate: Translate a matrix by premultiplication.
374
375
m: The matrix to translate
376
377
tx, ty: Translation distances along the X- and Y-axes. A
378
translation of 0 will not cause any translation along the
379
relevant axis.
380
381
Returns m.
382
383
Does not throw exceptions.
384
*/
385
fz_matrix *fz_pre_translate(fz_matrix *m, float tx, float ty);
386
387
/*
388
fz_invert_matrix: Create an inverse matrix.
389
390
inverse: Place to store inverse matrix.
391
392
matrix: Matrix to invert. A degenerate matrix, where the
393
determinant is equal to zero, can not be inverted and the
394
original matrix is returned instead.
395
396
Returns inverse.
397
398
Does not throw exceptions.
399
*/
400
fz_matrix *fz_invert_matrix(fz_matrix *inverse, const fz_matrix *matrix);
401
402
/*
403
fz_try_invert_matrix: Attempt to create an inverse matrix.
404
405
inverse: Place to store inverse matrix.
406
407
matrix: Matrix to invert. A degenerate matrix, where the
408
determinant is equal to zero, can not be inverted.
409
410
Returns 1 if matrix is degenerate (singular), or 0 otherwise.
411
412
Does not throw exceptions.
413
*/
414
int fz_try_invert_matrix(fz_matrix *inverse, const fz_matrix *matrix);
415
416
/*
417
fz_is_rectilinear: Check if a transformation is rectilinear.
418
419
Rectilinear means that no shearing is present and that any
420
rotations present are a multiple of 90 degrees. Usually this
421
is used to make sure that axis-aligned rectangles before the
422
transformation are still axis-aligned rectangles afterwards.
423
424
Does not throw exceptions.
425
*/
426
int fz_is_rectilinear(const fz_matrix *m);
427
428
/*
429
fz_matrix_expansion: Calculate average scaling factor of matrix.
430
*/
431
float fz_matrix_expansion(const fz_matrix *m); /* sumatrapdf */
432
433
/*
434
fz_intersect_rect: Compute intersection of two rectangles.
435
436
Given two rectangles, update the first to be the smallest
437
axis-aligned rectangle that covers the area covered by both
438
given rectangles. If either rectangle is empty then the
439
intersection is also empty. If either rectangle is infinite
440
then the intersection is simply the non-infinite rectangle.
441
Should both rectangles be infinite, then the intersection is
442
also infinite.
443
444
Does not throw exceptions.
445
*/
446
fz_rect *fz_intersect_rect(fz_rect *restrict a, const fz_rect *restrict b);
447
448
/*
449
fz_intersect_irect: Compute intersection of two bounding boxes.
450
451
Similar to fz_intersect_rect but operates on two bounding
452
boxes instead of two rectangles.
453
454
Does not throw exceptions.
455
*/
456
fz_irect *fz_intersect_irect(fz_irect *restrict a, const fz_irect *restrict b);
457
458
/*
459
fz_union_rect: Compute union of two rectangles.
460
461
Given two rectangles, update the first to be the smallest
462
axis-aligned rectangle that encompasses both given rectangles.
463
If either rectangle is infinite then the union is also infinite.
464
If either rectangle is empty then the union is simply the
465
non-empty rectangle. Should both rectangles be empty, then the
466
union is also empty.
467
468
Does not throw exceptions.
469
*/
470
fz_rect *fz_union_rect(fz_rect *restrict a, const fz_rect *restrict b);
471
472
/*
473
fz_irect_from_rect: Convert a rect into the minimal bounding box
474
that covers the rectangle.
475
476
bbox: Place to store the returned bbox.
477
478
rect: The rectangle to convert to a bbox.
479
480
Coordinates in a bounding box are integers, so rounding of the
481
rects coordinates takes place. The top left corner is rounded
482
upwards and left while the bottom right corner is rounded
483
downwards and to the right.
484
485
Returns bbox (updated).
486
487
Does not throw exceptions.
488
*/
489
490
fz_irect *fz_irect_from_rect(fz_irect *restrict bbox, const fz_rect *restrict rect);
491
492
/*
493
fz_round_rect: Round rectangle coordinates.
494
495
Coordinates in a bounding box are integers, so rounding of the
496
rects coordinates takes place. The top left corner is rounded
497
upwards and left while the bottom right corner is rounded
498
downwards and to the right.
499
500
This differs from fz_irect_from_rect, in that fz_irect_from_rect
501
slavishly follows the numbers (i.e any slight over/under calculations
502
can cause whole extra pixels to be added). fz_round_rect
503
allows for a small amount of rounding error when calculating
504
the bbox.
505
506
Does not throw exceptions.
507
*/
508
fz_irect *fz_round_rect(fz_irect *restrict bbox, const fz_rect *restrict rect);
509
510
/*
511
fz_rect_from_irect: Convert a bbox into a rect.
512
513
For our purposes, a rect can represent all the values we meet in
514
a bbox, so nothing can go wrong.
515
516
rect: A place to store the generated rectangle.
517
518
bbox: The bbox to convert.
519
520
Returns rect (updated).
521
522
Does not throw exceptions.
523
*/
524
fz_rect *fz_rect_from_irect(fz_rect *restrict rect, const fz_irect *restrict bbox);
525
526
/*
527
fz_expand_rect: Expand a bbox by a given amount in all directions.
528
529
Does not throw exceptions.
530
*/
531
fz_rect *fz_expand_rect(fz_rect *b, float expand);
532
533
/*
534
fz_include_point_in_rect: Expand a bbox to include a given point.
535
To create a rectangle that encompasses a sequence of points, the
536
rectangle must first be set to be the empty rectangle at one of
537
the points before including the others.
538
*/
539
fz_rect *fz_include_point_in_rect(fz_rect *r, const fz_point *p);
540
541
/*
542
fz_translate_irect: Translate bounding box.
543
544
Translate a bbox by a given x and y offset. Allows for overflow.
545
546
Does not throw exceptions.
547
*/
548
fz_irect *fz_translate_irect(fz_irect *a, int xoff, int yoff);
549
550
/*
551
fz_transform_point: Apply a transformation to a point.
552
553
transform: Transformation matrix to apply. See fz_concat,
554
fz_scale, fz_rotate and fz_translate for how to create a
555
matrix.
556
557
point: Pointer to point to update.
558
559
Returns transform (unchanged).
560
561
Does not throw exceptions.
562
*/
563
fz_point *fz_transform_point(fz_point *restrict point, const fz_matrix *restrict transform);
564
fz_point *fz_transform_point_xy(fz_point *restrict point, const fz_matrix *restrict transform, float x, float y);
565
566
/*
567
fz_transform_vector: Apply a transformation to a vector.
568
569
transform: Transformation matrix to apply. See fz_concat,
570
fz_scale and fz_rotate for how to create a matrix. Any
571
translation will be ignored.
572
573
vector: Pointer to vector to update.
574
575
Does not throw exceptions.
576
*/
577
fz_point *fz_transform_vector(fz_point *restrict vector, const fz_matrix *restrict transform);
578
579
/*
580
fz_transform_rect: Apply a transform to a rectangle.
581
582
After the four corner points of the axis-aligned rectangle
583
have been transformed it may not longer be axis-aligned. So a
584
new axis-aligned rectangle is created covering at least the
585
area of the transformed rectangle.
586
587
transform: Transformation matrix to apply. See fz_concat,
588
fz_scale and fz_rotate for how to create a matrix.
589
590
rect: Rectangle to be transformed. The two special cases
591
fz_empty_rect and fz_infinite_rect, may be used but are
592
returned unchanged as expected.
593
594
Does not throw exceptions.
595
*/
596
fz_rect *fz_transform_rect(fz_rect *restrict rect, const fz_matrix *restrict transform);
597
598
/*
599
fz_normalize_vector: Normalize a vector to length one.
600
*/
601
void fz_normalize_vector(fz_point *p);
602
603
void fz_gridfit_matrix(fz_matrix *m);
604
605
float fz_matrix_max_expansion(const fz_matrix *m);
606
607
#endif
608
609