Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7640 views
1
#include "mupdf/fitz.h"
2
3
#define MAX4(a,b,c,d) fz_max(fz_max(a,b), fz_max(c,d))
4
#define MIN4(a,b,c,d) fz_min(fz_min(a,b), fz_min(c,d))
5
6
/* A useful macro to add with overflow detection and clamping.
7
8
We want to do "b = a + x", but to allow for overflow. Consider the
9
top bits, and the cases in which overflow occurs:
10
11
overflow a x b ~a^x a^b (~a^x)&(a^b)
12
no 0 0 0 1 0 0
13
yes 0 0 1 1 1 1
14
no 0 1 0 0 0 0
15
no 0 1 1 0 1 0
16
no 1 0 0 0 1 0
17
no 1 0 1 0 0 0
18
yes 1 1 0 1 1 1
19
no 1 1 1 1 0 0
20
*/
21
#define ADD_WITH_SAT(b,a,x) \
22
((b) = (a) + (x), (b) = (((~(a)^(x))&((a)^(b))) < 0 ? ((x) < 0 ? INT_MIN : INT_MAX) : (b)))
23
24
/* Matrices, points and affine transformations */
25
26
const fz_matrix fz_identity = { 1, 0, 0, 1, 0, 0 };
27
28
fz_matrix *
29
fz_concat(fz_matrix *dst, const fz_matrix *one, const fz_matrix *two)
30
{
31
fz_matrix dst2;
32
dst2.a = one->a * two->a + one->b * two->c;
33
dst2.b = one->a * two->b + one->b * two->d;
34
dst2.c = one->c * two->a + one->d * two->c;
35
dst2.d = one->c * two->b + one->d * two->d;
36
dst2.e = one->e * two->a + one->f * two->c + two->e;
37
dst2.f = one->e * two->b + one->f * two->d + two->f;
38
*dst = dst2;
39
return dst;
40
}
41
42
fz_matrix *
43
fz_scale(fz_matrix *m, float sx, float sy)
44
{
45
m->a = sx; m->b = 0;
46
m->c = 0; m->d = sy;
47
m->e = 0; m->f = 0;
48
return m;
49
}
50
51
fz_matrix *
52
fz_pre_scale(fz_matrix *mat, float sx, float sy)
53
{
54
mat->a *= sx;
55
mat->b *= sx;
56
mat->c *= sy;
57
mat->d *= sy;
58
return mat;
59
}
60
61
fz_matrix *
62
fz_shear(fz_matrix *mat, float h, float v)
63
{
64
mat->a = 1; mat->b = v;
65
mat->c = h; mat->d = 1;
66
mat->e = 0; mat->f = 0;
67
return mat;
68
}
69
70
fz_matrix *
71
fz_pre_shear(fz_matrix *mat, float h, float v)
72
{
73
float a = mat->a;
74
float b = mat->b;
75
mat->a += v * mat->c;
76
mat->b += v * mat->d;
77
mat->c += h * a;
78
mat->d += h * b;
79
return mat;
80
}
81
82
fz_matrix *
83
fz_rotate(fz_matrix *m, float theta)
84
{
85
float s;
86
float c;
87
88
while (theta < 0)
89
theta += 360;
90
while (theta >= 360)
91
theta -= 360;
92
93
if (fabsf(0 - theta) < FLT_EPSILON)
94
{
95
s = 0;
96
c = 1;
97
}
98
else if (fabsf(90.0f - theta) < FLT_EPSILON)
99
{
100
s = 1;
101
c = 0;
102
}
103
else if (fabsf(180.0f - theta) < FLT_EPSILON)
104
{
105
s = 0;
106
c = -1;
107
}
108
else if (fabsf(270.0f - theta) < FLT_EPSILON)
109
{
110
s = -1;
111
c = 0;
112
}
113
else
114
{
115
s = sinf(theta * (float)M_PI / 180);
116
c = cosf(theta * (float)M_PI / 180);
117
}
118
119
m->a = c; m->b = s;
120
m->c = -s; m->d = c;
121
m->e = 0; m->f = 0;
122
return m;
123
}
124
125
fz_matrix *
126
fz_pre_rotate(fz_matrix *m, float theta)
127
{
128
while (theta < 0)
129
theta += 360;
130
while (theta >= 360)
131
theta -= 360;
132
133
if (fabsf(0 - theta) < FLT_EPSILON)
134
{
135
/* Nothing to do */
136
}
137
else if (fabsf(90.0f - theta) < FLT_EPSILON)
138
{
139
float a = m->a;
140
float b = m->b;
141
m->a = m->c;
142
m->b = m->d;
143
m->c = -a;
144
m->d = -b;
145
}
146
else if (fabsf(180.0f - theta) < FLT_EPSILON)
147
{
148
m->a = -m->a;
149
m->b = -m->b;
150
m->c = -m->c;
151
m->d = -m->d;
152
}
153
else if (fabsf(270.0f - theta) < FLT_EPSILON)
154
{
155
float a = m->a;
156
float b = m->b;
157
m->a = -m->c;
158
m->b = -m->d;
159
m->c = a;
160
m->d = b;
161
}
162
else
163
{
164
float s = sinf(theta * (float)M_PI / 180);
165
float c = cosf(theta * (float)M_PI / 180);
166
float a = m->a;
167
float b = m->b;
168
m->a = c * a + s * m->c;
169
m->b = c * b + s * m->d;
170
m->c =-s * a + c * m->c;
171
m->d =-s * b + c * m->d;
172
}
173
174
return m;
175
}
176
177
fz_matrix *
178
fz_translate(fz_matrix *m, float tx, float ty)
179
{
180
m->a = 1; m->b = 0;
181
m->c = 0; m->d = 1;
182
m->e = tx; m->f = ty;
183
return m;
184
}
185
186
fz_matrix *
187
fz_pre_translate(fz_matrix *mat, float tx, float ty)
188
{
189
mat->e += tx * mat->a + ty * mat->c;
190
mat->f += tx * mat->b + ty * mat->d;
191
return mat;
192
}
193
194
fz_matrix *
195
fz_invert_matrix(fz_matrix *dst, const fz_matrix *src)
196
{
197
/* Be careful to cope with dst == src */
198
float a = src->a;
199
float det = a * src->d - src->b * src->c;
200
if (det < -FLT_EPSILON || det > FLT_EPSILON)
201
{
202
float rdet = 1 / det;
203
dst->a = src->d * rdet;
204
dst->b = -src->b * rdet;
205
dst->c = -src->c * rdet;
206
dst->d = a * rdet;
207
a = -src->e * dst->a - src->f * dst->c;
208
dst->f = -src->e * dst->b - src->f * dst->d;
209
dst->e = a;
210
}
211
else
212
*dst = *src;
213
return dst;
214
}
215
216
int
217
fz_try_invert_matrix(fz_matrix *dst, const fz_matrix *src)
218
{
219
/* Be careful to cope with dst == src */
220
double sa = (double)src->a;
221
double sb = (double)src->b;
222
double sc = (double)src->c;
223
double sd = (double)src->d;
224
double da, db, dc, dd;
225
double det = sa * sd - sb * sc;
226
if (det >= -DBL_EPSILON && det <= DBL_EPSILON)
227
return 1;
228
det = 1 / det;
229
da = sd * det;
230
dst->a = (float)da;
231
db = -sb * det;
232
dst->b = (float)db;
233
dc = -sc * det;
234
dst->c = (float)dc;
235
dd = sa * det;
236
dst->d = (float)dd;
237
da = -src->e * da - src->f * dc;
238
dst->f = (float)(-src->e * db - src->f * dd);
239
dst->e = (float)da;
240
return 0;
241
}
242
243
int
244
fz_is_rectilinear(const fz_matrix *m)
245
{
246
return (fabsf(m->b) < FLT_EPSILON && fabsf(m->c) < FLT_EPSILON) ||
247
(fabsf(m->a) < FLT_EPSILON && fabsf(m->d) < FLT_EPSILON);
248
}
249
250
float
251
fz_matrix_expansion(const fz_matrix *m)
252
{
253
return sqrtf(fabsf(m->a * m->d - m->b * m->c));
254
}
255
256
float
257
fz_matrix_max_expansion(const fz_matrix *m)
258
{
259
float max = fabsf(m->a);
260
float x = fabsf(m->b);
261
if (max < x)
262
max = x;
263
x = fabsf(m->c);
264
if (max < x)
265
max = x;
266
x = fabsf(m->d);
267
if (max < x)
268
max = x;
269
return max;
270
}
271
272
fz_point *
273
fz_transform_point(fz_point *restrict p, const fz_matrix *restrict m)
274
{
275
float x = p->x;
276
p->x = x * m->a + p->y * m->c + m->e;
277
p->y = x * m->b + p->y * m->d + m->f;
278
return p;
279
}
280
281
fz_point *
282
fz_transform_point_xy(fz_point *restrict p, const fz_matrix *restrict m, float x, float y)
283
{
284
p->x = x * m->a + y * m->c + m->e;
285
p->y = x * m->b + y * m->d + m->f;
286
return p;
287
}
288
289
fz_point *
290
fz_transform_vector(fz_point *restrict p, const fz_matrix *restrict m)
291
{
292
float x = p->x;
293
p->x = x * m->a + p->y * m->c;
294
p->y = x * m->b + p->y * m->d;
295
return p;
296
}
297
298
void
299
fz_normalize_vector(fz_point *p)
300
{
301
float len = p->x * p->x + p->y * p->y;
302
if (len != 0)
303
{
304
len = sqrtf(len);
305
p->x /= len;
306
p->y /= len;
307
}
308
}
309
310
/* Rectangles and bounding boxes */
311
312
/* biggest and smallest integers that a float can represent perfectly (i.e. 24 bits) */
313
#define MAX_SAFE_INT 16777216
314
#define MIN_SAFE_INT -16777216
315
316
const fz_rect fz_infinite_rect = { 1, 1, -1, -1 };
317
const fz_rect fz_empty_rect = { 0, 0, 0, 0 };
318
const fz_rect fz_unit_rect = { 0, 0, 1, 1 };
319
320
const fz_irect fz_infinite_irect = { 1, 1, -1, -1 };
321
const fz_irect fz_empty_irect = { 0, 0, 0, 0 };
322
const fz_irect fz_unit_bbox = { 0, 0, 1, 1 };
323
324
fz_irect *
325
fz_irect_from_rect(fz_irect *restrict b, const fz_rect *restrict r)
326
{
327
if (fz_is_empty_rect(r))
328
{
329
b->x0 = 0;
330
b->y0 = 0;
331
b->x1 = 0;
332
b->y1 = 0;
333
}
334
else
335
{
336
b->x0 = fz_clamp(floorf(r->x0), MIN_SAFE_INT, MAX_SAFE_INT);
337
b->y0 = fz_clamp(floorf(r->y0), MIN_SAFE_INT, MAX_SAFE_INT);
338
b->x1 = fz_clamp(ceilf(r->x1), MIN_SAFE_INT, MAX_SAFE_INT);
339
b->y1 = fz_clamp(ceilf(r->y1), MIN_SAFE_INT, MAX_SAFE_INT);
340
}
341
return b;
342
}
343
344
fz_rect *
345
fz_rect_from_irect(fz_rect *restrict r, const fz_irect *restrict a)
346
{
347
r->x0 = a->x0;
348
r->y0 = a->y0;
349
r->x1 = a->x1;
350
r->y1 = a->y1;
351
return r;
352
}
353
354
fz_irect *
355
fz_round_rect(fz_irect * restrict b, const fz_rect *restrict r)
356
{
357
int i;
358
359
i = floorf(r->x0 + 0.001);
360
b->x0 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
361
i = floorf(r->y0 + 0.001);
362
b->y0 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
363
i = ceilf(r->x1 - 0.001);
364
b->x1 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
365
i = ceilf(r->y1 - 0.001);
366
b->y1 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
367
368
return b;
369
}
370
371
fz_rect *
372
fz_intersect_rect(fz_rect *restrict a, const fz_rect *restrict b)
373
{
374
/* Check for empty box before infinite box */
375
if (fz_is_empty_rect(a)) return a;
376
if (fz_is_empty_rect(b)) {
377
*a = fz_empty_rect;
378
return a;
379
}
380
if (fz_is_infinite_rect(b)) return a;
381
if (fz_is_infinite_rect(a)) {
382
*a = *b;
383
return a;
384
}
385
if (a->x0 < b->x0)
386
a->x0 = b->x0;
387
if (a->y0 < b->y0)
388
a->y0 = b->y0;
389
if (a->x1 > b->x1)
390
a->x1 = b->x1;
391
if (a->y1 > b->y1)
392
a->y1 = b->y1;
393
if (a->x1 < a->x0 || a->y1 < a->y0)
394
*a = fz_empty_rect;
395
return a;
396
}
397
398
fz_irect *
399
fz_intersect_irect(fz_irect *restrict a, const fz_irect *restrict b)
400
{
401
/* Check for empty box before infinite box */
402
if (fz_is_empty_irect(a)) return a;
403
if (fz_is_empty_irect(b))
404
{
405
*a = fz_empty_irect;
406
return a;
407
}
408
if (fz_is_infinite_irect(b)) return a;
409
if (fz_is_infinite_irect(a))
410
{
411
*a = *b;
412
return a;
413
}
414
if (a->x0 < b->x0)
415
a->x0 = b->x0;
416
if (a->y0 < b->y0)
417
a->y0 = b->y0;
418
if (a->x1 > b->x1)
419
a->x1 = b->x1;
420
if (a->y1 > b->y1)
421
a->y1 = b->y1;
422
if (a->x1 < a->x0 || a->y1 < a->y0)
423
*a = fz_empty_irect;
424
return a;
425
}
426
427
fz_rect *
428
fz_union_rect(fz_rect *restrict a, const fz_rect *restrict b)
429
{
430
/* Check for empty box before infinite box */
431
if (fz_is_empty_rect(b)) return a;
432
if (fz_is_empty_rect(a)) {
433
*a = *b;
434
return a;
435
}
436
if (fz_is_infinite_rect(a)) return a;
437
if (fz_is_infinite_rect(b)) {
438
*a = *b;
439
return a;
440
}
441
if (a->x0 > b->x0)
442
a->x0 = b->x0;
443
if (a->y0 > b->y0)
444
a->y0 = b->y0;
445
if (a->x1 < b->x1)
446
a->x1 = b->x1;
447
if (a->y1 < b->y1)
448
a->y1 = b->y1;
449
return a;
450
}
451
452
fz_irect *
453
fz_translate_irect(fz_irect *a, int xoff, int yoff)
454
{
455
int t;
456
457
if (fz_is_empty_irect(a)) return a;
458
if (fz_is_infinite_irect(a)) return a;
459
a->x0 = ADD_WITH_SAT(t, a->x0, xoff);
460
a->y0 = ADD_WITH_SAT(t, a->y0, yoff);
461
a->x1 = ADD_WITH_SAT(t, a->x1, xoff);
462
a->y1 = ADD_WITH_SAT(t, a->y1, yoff);
463
return a;
464
}
465
466
fz_rect *
467
fz_transform_rect(fz_rect *restrict r, const fz_matrix *restrict m)
468
{
469
fz_point s, t, u, v;
470
471
if (fz_is_infinite_rect(r))
472
return r;
473
474
if (fabsf(m->b) < FLT_EPSILON && fabsf(m->c) < FLT_EPSILON)
475
{
476
if (m->a < 0)
477
{
478
float f = r->x0;
479
r->x0 = r->x1;
480
r->x1 = f;
481
}
482
if (m->d < 0)
483
{
484
float f = r->y0;
485
r->y0 = r->y1;
486
r->y1 = f;
487
}
488
fz_transform_point(fz_rect_min(r), m);
489
fz_transform_point(fz_rect_max(r), m);
490
return r;
491
}
492
493
s.x = r->x0; s.y = r->y0;
494
t.x = r->x0; t.y = r->y1;
495
u.x = r->x1; u.y = r->y1;
496
v.x = r->x1; v.y = r->y0;
497
fz_transform_point(&s, m);
498
fz_transform_point(&t, m);
499
fz_transform_point(&u, m);
500
fz_transform_point(&v, m);
501
r->x0 = MIN4(s.x, t.x, u.x, v.x);
502
r->y0 = MIN4(s.y, t.y, u.y, v.y);
503
r->x1 = MAX4(s.x, t.x, u.x, v.x);
504
r->y1 = MAX4(s.y, t.y, u.y, v.y);
505
return r;
506
}
507
508
fz_rect *
509
fz_expand_rect(fz_rect *a, float expand)
510
{
511
if (fz_is_empty_rect(a)) return a;
512
if (fz_is_infinite_rect(a)) return a;
513
a->x0 -= expand;
514
a->y0 -= expand;
515
a->x1 += expand;
516
a->y1 += expand;
517
return a;
518
}
519
520
fz_rect *fz_include_point_in_rect(fz_rect *r, const fz_point *p)
521
{
522
if (p->x < r->x0) r->x0 = p->x;
523
if (p->x > r->x1) r->x1 = p->x;
524
if (p->y < r->y0) r->y0 = p->y;
525
if (p->y > r->y1) r->y1 = p->y;
526
527
return r;
528
}
529
530