return q;
}
-#endif
+/* Add the specified unsigned 32-bit N to the large integer
+ INTEGER. */
+
+static void
+sfnt_large_integer_add (struct sfnt_large_integer *integer,
+ uint32_t n)
+{
+ struct sfnt_large_integer number;
+
+ number.low = integer->low + n;
+ number.high = integer->high + (number.low
+ < integer->low);
+
+ *integer = number;
+}
+
+#endif /* !INT64_MAX */
/* Calculate (A * B) / C with no rounding and return the result, using
a 64 bit integer if necessary. */
sfnt_multiply_divide_1 (a, b, &temp);
return sfnt_multiply_divide_2 (&temp, c);
-#else
+#else /* INT64_MAX */
uint64_t temp;
temp = (uint64_t) a * (uint64_t) b;
return temp / c;
-#endif
+#endif /* !INT64_MAX */
}
-#ifndef INT64_MAX
+/* Calculate (A * B) / C with rounding and return the result, using a
+ 64 bit integer if necessary. */
-/* Add the specified unsigned 32-bit N to the large integer
- INTEGER. */
-
-static void
-sfnt_large_integer_add (struct sfnt_large_integer *integer,
- uint32_t n)
+static unsigned int
+sfnt_multiply_divide_rounded (unsigned int a, unsigned int b,
+ unsigned int c)
{
- struct sfnt_large_integer number;
+#ifndef INT64_MAX
+ struct sfnt_large_integer temp;
- number.low = integer->low + n;
- number.high = integer->high + (number.low
- < integer->low);
+ sfnt_multiply_divide_1 (a, b, &temp);
+ sfnt_large_integer_add (&temp, c / 2);
+ return sfnt_multiply_divide_2 (&temp, c);
+#else /* INT64_MAX */
+ uint64_t temp;
- *integer = number;
+ temp = (uint64_t) a * (uint64_t) b + c / 2;
+ return temp / c;
+#endif /* !INT64_MAX */
}
+#ifndef INT64_MAX
+
/* Calculate (A * B) / C, rounding the result with a threshold of N.
Use a 64 bit temporary. */
return sfnt_multiply_divide_2 (&temp, c);
}
-#endif /* INT64_MAX */
+#endif /* !INT64_MAX */
-/* The same as sfnt_multiply_divide, but handle signed values
+/* The same as sfnt_multiply_divide_rounded, but handle signed values
instead. */
MAYBE_UNUSED static int
if (c < 0)
sign = -sign;
- return (sfnt_multiply_divide (abs (a), abs (b), abs (c))
- * sign);
+ return (sfnt_multiply_divide_rounded (abs (a), abs (b),
+ abs (c)) * sign);
}
/* Multiply the two 16.16 fixed point numbers X and Y. Return the
/* This can be done quickly with int64_t. */
return product / (int64_t) 65536;
-#else
+#else /* !INT64_MAX */
int sign;
sign = 1;
return sfnt_multiply_divide (abs (x), abs (y),
65536) * sign;
-#endif
+#endif /* INT64_MAX */
}
/* Multiply the two 16.16 fixed point numbers X and Y, with rounding
/* This can be done quickly with int64_t. */
return (product + round) / (int64_t) 65536;
-#else
+#else /* !INT64_MAX */
int sign;
sign = 1;
return sfnt_multiply_divide_round (abs (x), abs (y),
32768, 65536) * sign;
-#endif
+#endif /* INT64_MAX */
}
/* Set the pen size to the specified point and return. POINT will be
sign = -sign;
sfnt_multiply_divide_1 (abs (x), abs (y), &temp);
- sfnt_large_integer_add (&temp, 32676);
+ sfnt_large_integer_add (&temp, 32768);
return sfnt_multiply_divide_2 (&temp, 65536) * sign;
#endif
}
? interpreter->glyph_zone->x_points[p] \
: interpreter->glyph_zone->y_points[p])
+#define load_unscaled(p) \
+ (opcode == 0x31 \
+ ? interpreter->glyph_zone->simple->x_coordinates[p] \
+ : interpreter->glyph_zone->simple->y_coordinates[p])
+
#define IUP_SINGLE_PAIR() \
/* Now make touch_start the first point before, i.e. the first \
touched point in this pair. */ \
if (position >= original_min_pos \
&& position <= original_max_pos) \
{ \
+ /* Compute the ratio between the two touched point positions \
+ and the original position of the point being touched with \
+ positions from the unscaled outline, if at all \
+ possible. */ \
+ \
+ if (interpreter->glyph_zone->simple) \
+ { \
+ org_max_pos = load_unscaled (point_max); \
+ org_min_pos = load_unscaled (point_min); \
+ position = load_unscaled (i); \
+ } \
+ else \
+ { \
+ org_max_pos = original_max_pos; \
+ org_min_pos = original_min_pos; \
+ } \
+ \
/* Handle the degenerate case where original_min_pos and \
original_max_pos have not changed by placing the point in \
the middle. */ \
- if (original_min_pos == original_max_pos) \
+ if (org_min_pos == org_max_pos) \
ratio = 077777; \
else \
/* ... preserve the ratio of i between min_pos and \
max_pos... */ \
ratio = sfnt_div_fixed ((sfnt_sub (position, \
- original_min_pos) \
+ org_min_pos) \
* 1024), \
- (sfnt_sub (original_max_pos, \
- original_min_pos) \
+ (sfnt_sub (org_max_pos, \
+ org_min_pos) \
* 1024)); \
\
delta = sfnt_sub (max_pos, min_pos); \
- delta = sfnt_mul_fixed (ratio, delta); \
+ delta = sfnt_mul_fixed_round (ratio, delta); \
store_point (i, sfnt_add (min_pos, delta)); \
} \
else \
size_t first_point;
size_t point_min, point_max, i;
sfnt_f26dot6 position, min_pos, max_pos, delta, ratio;
- sfnt_f26dot6 original_max_pos;
- sfnt_f26dot6 original_min_pos;
+ sfnt_f26dot6 original_max_pos, org_max_pos;
+ sfnt_f26dot6 original_min_pos, org_min_pos;
/* Find the first touched point. If none is found, simply
return. */
#undef load_point
#undef store_point
#undef load_original
+#undef load_unscaled
/* Interpret an IUP (``interpolate untouched points'') instruction.
INTERPRETER is the interpreter, and OPCODE is the instruction