| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- #include "fitz-internal.h"
- #define MAX4(a,b,c,d) fz_max(fz_max(a,b), fz_max(c,d))
- #define MIN4(a,b,c,d) fz_min(fz_min(a,b), fz_min(c,d))
- /* A useful macro to add with overflow detection and clamping.
- We want to do "b = a + x", but to allow for overflow. Consider the
- top bits, and the cases in which overflow occurs:
- overflow a x b ~a^x a^b (~a^x)&(a^b)
- no 0 0 0 1 0 0
- yes 0 0 1 1 1 1
- no 0 1 0 0 0 0
- no 0 1 1 0 1 0
- no 1 0 0 0 1 0
- no 1 0 1 0 0 0
- yes 1 1 0 1 1 1
- no 1 1 1 1 0 0
- */
- #define ADD_WITH_SAT(b,a,x) \
- ((b) = (a) + (x), (b) = (((~(a)^(x))&((a)^(b))) < 0 ? ((x) < 0 ? INT_MIN : INT_MAX) : (b)))
- /* Matrices, points and affine transformations */
- const fz_matrix fz_identity = { 1, 0, 0, 1, 0, 0 };
- fz_matrix *
- fz_concat(fz_matrix *dst, const fz_matrix *one, const fz_matrix *two)
- {
- fz_matrix dst2;
- dst2.a = one->a * two->a + one->b * two->c;
- dst2.b = one->a * two->b + one->b * two->d;
- dst2.c = one->c * two->a + one->d * two->c;
- dst2.d = one->c * two->b + one->d * two->d;
- dst2.e = one->e * two->a + one->f * two->c + two->e;
- dst2.f = one->e * two->b + one->f * two->d + two->f;
- *dst = dst2;
- return dst;
- }
- fz_matrix *
- fz_scale(fz_matrix *m, float sx, float sy)
- {
- m->a = sx; m->b = 0;
- m->c = 0; m->d = sy;
- m->e = 0; m->f = 0;
- return m;
- }
- fz_matrix *
- fz_pre_scale(fz_matrix *mat, float sx, float sy)
- {
- mat->a *= sx;
- mat->b *= sx;
- mat->c *= sy;
- mat->d *= sy;
- return mat;
- }
- fz_matrix *
- fz_shear(fz_matrix *mat, float h, float v)
- {
- mat->a = 1; mat->b = v;
- mat->c = h; mat->d = 1;
- mat->e = 0; mat->f = 0;
- return mat;
- }
- fz_matrix *
- fz_pre_shear(fz_matrix *mat, float h, float v)
- {
- float a = mat->a;
- float b = mat->b;
- mat->a += v * mat->c;
- mat->b += v * mat->d;
- mat->c += h * a;
- mat->d += h * b;
- return mat;
- }
- fz_matrix *
- fz_rotate(fz_matrix *m, float theta)
- {
- float s;
- float c;
- while (theta < 0)
- theta += 360;
- while (theta >= 360)
- theta -= 360;
- if (fabsf(0 - theta) < FLT_EPSILON)
- {
- s = 0;
- c = 1;
- }
- else if (fabsf(90.0f - theta) < FLT_EPSILON)
- {
- s = 1;
- c = 0;
- }
- else if (fabsf(180.0f - theta) < FLT_EPSILON)
- {
- s = 0;
- c = -1;
- }
- else if (fabsf(270.0f - theta) < FLT_EPSILON)
- {
- s = -1;
- c = 0;
- }
- else
- {
- s = sinf(theta * (float)M_PI / 180);
- c = cosf(theta * (float)M_PI / 180);
- }
- m->a = c; m->b = s;
- m->c = -s; m->d = c;
- m->e = 0; m->f = 0;
- return m;
- }
- fz_matrix *
- fz_pre_rotate(fz_matrix *m, float theta)
- {
- while (theta < 0)
- theta += 360;
- while (theta >= 360)
- theta -= 360;
- if (fabsf(0 - theta) < FLT_EPSILON)
- {
- /* Nothing to do */
- }
- else if (fabsf(90.0f - theta) < FLT_EPSILON)
- {
- float a = m->a;
- float b = m->b;
- m->a = m->c;
- m->b = m->d;
- m->c = -a;
- m->d = -b;
- }
- else if (fabsf(180.0f - theta) < FLT_EPSILON)
- {
- m->a = -m->a;
- m->b = -m->b;
- m->c = -m->c;
- m->d = -m->d;
- }
- else if (fabsf(270.0f - theta) < FLT_EPSILON)
- {
- float a = m->a;
- float b = m->b;
- m->a = -m->c;
- m->b = -m->d;
- m->c = a;
- m->d = b;
- }
- else
- {
- float s = sinf(theta * (float)M_PI / 180);
- float c = cosf(theta * (float)M_PI / 180);
- float a = m->a;
- float b = m->b;
- m->a = c * a + s * m->c;
- m->b = c * b + s * m->d;
- m->c =-s * a + c * m->c;
- m->d =-s * b + c * m->d;
- }
- return m;
- }
- fz_matrix *
- fz_translate(fz_matrix *m, float tx, float ty)
- {
- m->a = 1; m->b = 0;
- m->c = 0; m->d = 1;
- m->e = tx; m->f = ty;
- return m;
- }
- fz_matrix *
- fz_pre_translate(fz_matrix *mat, float tx, float ty)
- {
- mat->e += tx * mat->a + ty * mat->c;
- mat->f += tx * mat->b + ty * mat->d;
- return mat;
- }
- fz_matrix *
- fz_invert_matrix(fz_matrix *dst, const fz_matrix *src)
- {
- /* Be careful to cope with dst == src */
- float a = src->a;
- float det = a * src->d - src->b * src->c;
- if (det < -FLT_EPSILON || det > FLT_EPSILON)
- {
- float rdet = 1 / det;
- dst->a = src->d * rdet;
- dst->b = -src->b * rdet;
- dst->c = -src->c * rdet;
- dst->d = a * rdet;
- a = -src->e * dst->a - src->f * dst->c;
- dst->f = -src->e * dst->b - src->f * dst->d;
- dst->e = a;
- }
- else
- *dst = *src;
- return dst;
- }
- int
- fz_is_rectilinear(const fz_matrix *m)
- {
- return (fabsf(m->b) < FLT_EPSILON && fabsf(m->c) < FLT_EPSILON) ||
- (fabsf(m->a) < FLT_EPSILON && fabsf(m->d) < FLT_EPSILON);
- }
- float
- fz_matrix_expansion(const fz_matrix *m)
- {
- return sqrtf(fabsf(m->a * m->d - m->b * m->c));
- }
- float
- fz_matrix_max_expansion(const fz_matrix *m)
- {
- float max = fabsf(m->a);
- float x = fabsf(m->b);
- if (max < x)
- max = x;
- x = fabsf(m->c);
- if (max < x)
- max = x;
- x = fabsf(m->d);
- if (max < x)
- max = x;
- return max;
- }
- fz_point *
- fz_transform_point(fz_point *restrict p, const fz_matrix *restrict m)
- {
- float x = p->x;
- p->x = x * m->a + p->y * m->c + m->e;
- p->y = x * m->b + p->y * m->d + m->f;
- return p;
- }
- fz_point *
- fz_transform_vector(fz_point *restrict p, const fz_matrix *restrict m)
- {
- float x = p->x;
- p->x = x * m->a + p->y * m->c;
- p->y = x * m->b + p->y * m->d;
- return p;
- }
- /* Rectangles and bounding boxes */
- /* biggest and smallest integers that a float can represent perfectly (i.e. 24 bits) */
- #define MAX_SAFE_INT 16777216
- #define MIN_SAFE_INT -16777216
- const fz_rect fz_infinite_rect = { 1, 1, -1, -1 };
- const fz_rect fz_empty_rect = { 0, 0, 0, 0 };
- const fz_rect fz_unit_rect = { 0, 0, 1, 1 };
- const fz_irect fz_infinite_irect = { 1, 1, -1, -1 };
- const fz_irect fz_empty_irect = { 0, 0, 0, 0 };
- const fz_irect fz_unit_bbox = { 0, 0, 1, 1 };
- fz_irect *
- fz_irect_from_rect(fz_irect *restrict b, const fz_rect *restrict r)
- {
- b->x0 = fz_clamp(floorf(r->x0), MIN_SAFE_INT, MAX_SAFE_INT);
- b->y0 = fz_clamp(floorf(r->y0), MIN_SAFE_INT, MAX_SAFE_INT);
- b->x1 = fz_clamp(ceilf(r->x1), MIN_SAFE_INT, MAX_SAFE_INT);
- b->y1 = fz_clamp(ceilf(r->y1), MIN_SAFE_INT, MAX_SAFE_INT);
- return b;
- }
- fz_rect *
- fz_rect_from_irect(fz_rect *restrict r, const fz_irect *restrict a)
- {
- r->x0 = a->x0;
- r->y0 = a->y0;
- r->x1 = a->x1;
- r->y1 = a->y1;
- return r;
- }
- fz_irect *
- fz_round_rect(fz_irect * restrict b, const fz_rect *restrict r)
- {
- int i;
- i = floorf(r->x0 + 0.001);
- b->x0 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
- i = floorf(r->y0 + 0.001);
- b->y0 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
- i = ceilf(r->x1 - 0.001);
- b->x1 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
- i = ceilf(r->y1 - 0.001);
- b->y1 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
- return b;
- }
- fz_rect *
- fz_intersect_rect(fz_rect *restrict a, const fz_rect *restrict b)
- {
- /* Check for empty box before infinite box */
- if (fz_is_empty_rect(a)) return a;
- if (fz_is_empty_rect(b)) {
- *a = fz_empty_rect;
- return a;
- }
- if (fz_is_infinite_rect(b)) return a;
- if (fz_is_infinite_rect(a)) {
- *a = *b;
- return a;
- }
- if (a->x0 < b->x0)
- a->x0 = b->x0;
- if (a->y0 < b->y0)
- a->y0 = b->y0;
- if (a->x1 > b->x1)
- a->x1 = b->x1;
- if (a->y1 > b->y1)
- a->y1 = b->y1;
- if (a->x1 < a->x0 || a->y1 < a->y0)
- *a = fz_empty_rect;
- return a;
- }
- fz_irect *
- fz_intersect_irect(fz_irect *restrict a, const fz_irect *restrict b)
- {
- /* Check for empty box before infinite box */
- if (fz_is_empty_irect(a)) return a;
- if (fz_is_empty_irect(b))
- {
- *a = fz_empty_irect;
- return a;
- }
- if (fz_is_infinite_irect(b)) return a;
- if (fz_is_infinite_irect(a))
- {
- *a = *b;
- return a;
- }
- if (a->x0 < b->x0)
- a->x0 = b->x0;
- if (a->y0 < b->y0)
- a->y0 = b->y0;
- if (a->x1 > b->x1)
- a->x1 = b->x1;
- if (a->y1 > b->y1)
- a->y1 = b->y1;
- if (a->x1 < a->x0 || a->y1 < a->y0)
- *a = fz_empty_irect;
- return a;
- }
- fz_rect *
- fz_union_rect(fz_rect *restrict a, const fz_rect *restrict b)
- {
- /* Check for empty box before infinite box */
- if (fz_is_empty_rect(b)) return a;
- if (fz_is_empty_rect(a)) {
- *a = *b;
- return a;
- }
- if (fz_is_infinite_rect(a)) return a;
- if (fz_is_infinite_rect(b)) {
- *a = *b;
- return a;
- }
- if (a->x0 > b->x0)
- a->x0 = b->x0;
- if (a->y0 > b->y0)
- a->y0 = b->y0;
- if (a->x1 < b->x1)
- a->x1 = b->x1;
- if (a->y1 < b->y1)
- a->y1 = b->y1;
- return a;
- }
- fz_irect *
- fz_translate_irect(fz_irect *a, int xoff, int yoff)
- {
- int t;
- if (fz_is_empty_irect(a)) return a;
- if (fz_is_infinite_irect(a)) return a;
- a->x0 = ADD_WITH_SAT(t, a->x0, xoff);
- a->y0 = ADD_WITH_SAT(t, a->y0, yoff);
- a->x1 = ADD_WITH_SAT(t, a->x1, xoff);
- a->y1 = ADD_WITH_SAT(t, a->y1, yoff);
- return a;
- }
- fz_rect *
- fz_transform_rect(fz_rect *restrict r, const fz_matrix *restrict m)
- {
- fz_point s, t, u, v;
- if (fz_is_infinite_rect(r))
- return r;
- if (fabsf(m->b) < FLT_EPSILON && fabsf(m->c) < FLT_EPSILON)
- {
- if (m->a < 0)
- {
- float f = r->x0;
- r->x0 = r->x1;
- r->x1 = f;
- }
- if (m->d < 0)
- {
- float f = r->y0;
- r->y0 = r->y1;
- r->y1 = f;
- }
- fz_transform_point(fz_rect_min(r), m);
- fz_transform_point(fz_rect_max(r), m);
- return r;
- }
- s.x = r->x0; s.y = r->y0;
- t.x = r->x0; t.y = r->y1;
- u.x = r->x1; u.y = r->y1;
- v.x = r->x1; v.y = r->y0;
- fz_transform_point(&s, m);
- fz_transform_point(&t, m);
- fz_transform_point(&u, m);
- fz_transform_point(&v, m);
- r->x0 = MIN4(s.x, t.x, u.x, v.x);
- r->y0 = MIN4(s.y, t.y, u.y, v.y);
- r->x1 = MAX4(s.x, t.x, u.x, v.x);
- r->y1 = MAX4(s.y, t.y, u.y, v.y);
- return r;
- }
- fz_rect *
- fz_expand_rect(fz_rect *a, float expand)
- {
- if (fz_is_empty_rect(a)) return a;
- if (fz_is_infinite_rect(a)) return a;
- a->x0 -= expand;
- a->y0 -= expand;
- a->x1 += expand;
- a->y1 += expand;
- return a;
- }
|