static force_inline int
count_leading_zeros (uint32_t x)
{ #ifdef HAVE_BUILTIN_CLZ return __builtin_clz (x); #else int n = 0; while (x)
{
n++;
x >>= 1;
} return 32 - n; #endif
}
/* * Large signed/unsigned integer division with rounding for the platforms with * only 64-bit integer data type supported (no 128-bit data type). * * Arguments: * hi, lo - high and low 64-bit parts of the dividend * div - 48-bit divisor * * Returns: lowest 64 bits of the result as a return value and highest 64 * bits of the result to "result_hi" pointer
*/
/* round to nearest */ if (remainder * 2 >= div && ++result_lo == 0)
*result_hi += 1;
return result_lo;
}
/* signed division (128-bit by 49-bit) with rounding to nearest */ staticinline int64_t
rounded_sdiv_128_by_49 (int64_t hi,
uint64_t lo,
int64_t div,
int64_t *signed_result_hi)
{
uint64_t result_lo, result_hi; int sign = 0; if (div < 0)
{
div = -div;
sign ^= 1;
} if (hi < 0)
{ if (lo != 0)
hi++;
hi = -hi;
lo = -lo;
sign ^= 1;
}
result_lo = rounded_udiv_128_by_48 (hi, lo, div, &result_hi); if (sign)
{ if (result_lo != 0)
result_hi++;
result_hi = -result_hi;
result_lo = -result_lo;
} if (signed_result_hi)
{
*signed_result_hi = result_hi;
} return result_lo;
}
/* * Multiply 64.16 fixed point value by (2^scalebits) and convert * to 128-bit integer.
*/ static force_inline void
fixed_64_16_to_int128 (int64_t hi,
int64_t lo,
int64_t *rhi,
int64_t *rlo, int scalebits)
{ /* separate integer and fractional parts */
hi += lo >> 16;
lo &= 0xFFFF;
if (scalebits <= 0)
{
*rlo = hi >> (-scalebits);
*rhi = *rlo >> 63;
} else
{
*rhi = hi >> (64 - scalebits);
*rlo = (uint64_t)hi << scalebits; if (scalebits < 16)
*rlo += lo >> (16 - scalebits); else
*rlo += lo << (scalebits - 16);
}
}
/* * Convert 112.16 fixed point value to 48.16 with clamping for the out * of range values.
*/ static force_inline pixman_fixed_48_16_t
fixed_112_16_to_fixed_48_16 (int64_t hi, int64_t lo, pixman_bool_t *clampflag)
{ if ((lo >> 63) != hi)
{
*clampflag = TRUE; return hi >= 0 ? INT64_MAX : INT64_MIN;
} else
{ return lo;
}
}
/* * Transform a point with 31.16 fixed point coordinates from the destination * space to a point with 48.16 fixed point coordinates in the source space. * No overflows are possible for affine transformations and the results are * accurate including the least significant bit. Projective transformations * may overflow, in this case the results are just clamped to return maximum * or minimum 48.16 values (so that the caller can at least handle the NONE * and PAD repeats correctly) and the return value is FALSE to indicate that * such clamping has happened.
*/
PIXMAN_EXPORT pixman_bool_t
pixman_transform_point_31_16 (const pixman_transform_t *t, const pixman_vector_48_16_t *v,
pixman_vector_48_16_t *result)
{
pixman_bool_t clampflag = FALSE; int i;
int64_t tmp[3][2], divint;
uint16_t divfrac;
/* input vector values must have no more than 31 bits (including sign)
* in the integer part */
assert (v->v[0] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
assert (v->v[1] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
assert (v->v[2] < ((pixman_fixed_48_16_t)1 << (30 + 16)));
assert (v->v[2] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
/* * separate 64-bit integer and 16-bit fractional parts for the divisor, * which is also scaled by 65536 after fixed point multiplication.
*/
divint = tmp[2][0] + (tmp[2][1] >> 16);
divfrac = tmp[2][1] & 0xFFFF;
if (divint == pixman_fixed_1 && divfrac == 0)
{ /* * this is a simple affine transformation
*/
result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
result->v[2] = pixman_fixed_1;
} elseif (divint == 0 && divfrac == 0)
{ /* * handle zero divisor (if the values are non-zero, set the * results to maximum positive or minimum negative)
*/
clampflag = TRUE;
if (result->v[1] > 0)
result->v[1] = INT64_MAX; elseif (result->v[1] < 0)
result->v[1] = INT64_MIN;
} else
{ /* * projective transformation, analyze the top 32 bits of the divisor
*/
int32_t hi32divbits = divint >> 32; if (hi32divbits < 0)
hi32divbits = ~hi32divbits;
if (hi32divbits == 0)
{ /* the divisor is small, we can actually keep all the bits */
int64_t hi, rhi, lo, rlo;
int64_t div = ((uint64_t)divint << 16) + divfrac;
if (!pixman_transform_multiply (&t, a, b)) returnFALSE;
return pixman_transform_is_identity (&t);
}
PIXMAN_EXPORT void
pixman_f_transform_from_pixman_transform (struct pixman_f_transform * ft, conststruct pixman_transform *t)
{ int i, j;
for (j = 0; j < 3; j++)
{ for (i = 0; i < 3; i++)
ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
}
}
PIXMAN_EXPORT pixman_bool_t
pixman_transform_from_pixman_f_transform (struct pixman_transform * t, conststruct pixman_f_transform *ft)
{ int i, j;
for (j = 0; j < 3; j++)
{ for (i = 0; i < 3; i++)
{ double d = ft->m[j][i]; if (d < -32767.0 || d > 32767.0) returnFALSE;
d = d * 65536.0 + 0.5;
t->matrix[j][i] = (pixman_fixed_t) floor (d);
}
}
det = 0; for (i = 0; i < 3; i++)
{ double p; int ai = a[i]; int bi = b[i];
p = src->m[i][0] * (src->m[ai][2] * src->m[bi][1] -
src->m[ai][1] * src->m[bi][2]); if (i == 1)
p = -p;
det += p;
}
if (det == 0) returnFALSE;
det = 1 / det; for (j = 0; j < 3; j++)
{ for (i = 0; i < 3; i++)
{ double p; int ai = a[i]; int aj = a[j]; int bi = b[i]; int bj = b[j];
p = (src->m[ai][aj] * src->m[bi][bj] -
src->m[ai][bj] * src->m[bi][aj]);
if (((i + j) & 1) != 0)
p = -p;
d.m[j][i] = det * p;
}
}
*dst = d;
returnTRUE;
}
PIXMAN_EXPORT pixman_bool_t
pixman_f_transform_point (conststruct pixman_f_transform *t, struct pixman_f_vector * v)
{ struct pixman_f_vector result; int i, j; double a;
for (j = 0; j < 3; j++)
{
a = 0; for (i = 0; i < 3; i++)
a += t->m[j][i] * v->v[i];
result.v[j] = a;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.