#endif
}
+#ifndef INT64_MAX
+
+/* 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;
+}
+
+/* Calculate (A * B) / C, rounding the result with a threshold of N.
+ Use a 64 bit temporary. */
+
+static unsigned int
+sfnt_multiply_divide_round (unsigned int a, unsigned int b,
+ unsigned int n, unsigned int c)
+{
+ struct sfnt_large_integer temp;
+
+ sfnt_multiply_divide_1 (a, b, &temp);
+ sfnt_large_integer_add (&temp, n);
+ return sfnt_multiply_divide_2 (&temp, c);
+}
+
+#endif /* INT64_MAX */
+
/* The same as sfnt_multiply_divide, but handle signed values
instead. */
#endif
}
+/* Multiply the two 16.16 fixed point numbers X and Y, with rounding
+ of the result. */
+
+static sfnt_fixed
+sfnt_mul_fixed_round (sfnt_fixed x, sfnt_fixed y)
+{
+#ifdef INT64_MAX
+ int64_t product, round;
+
+ product = (int64_t) x * (int64_t) y;
+ round = product < 0 ? -32768 : 32768;
+
+ /* This can be done quickly with int64_t. */
+ return (product + round) / (int64_t) 65536;
+#else
+ int sign;
+
+ sign = 1;
+
+ if (x < 0)
+ sign = -sign;
+
+ if (y < 0)
+ sign = -sign;
+
+ return sfnt_multiply_divide_round (abs (x), abs (y),
+ 32768, 65536) * sign;
+#endif
+}
+
/* Set the pen size to the specified point and return. POINT will be
scaled up to the pixel size. */
SCALE is a scale factor that converts between em space and device
space.
- Use the scaled glyph METRICS to determine the origin point of the
+ Use the unscaled glyph METRICS to determine the origin point of the
outline.
Call GET_GLYPH and FREE_GLYPH with the specified DCONTEXT to obtain
return NULL;
}
- /* Compute the origin position. */
- origin = outline->xmin - metrics->lbearing;
- outline->origin
- = (origin + sfnt_mul_fixed (glyph->origin_distortion,
- build_outline_context.factor));
+ /* Compute the origin position. Note that the original glyph xmin
+ is first used to calculate the origin point, and the origin
+ distortion is applied to it to get the distorted origin. */
+
+ origin = glyph->xmin - metrics->lbearing + glyph->origin_distortion;
+ outline->origin = sfnt_mul_fixed (origin, scale);
return outline;
}
{
raster->width
= (sfnt_ceil_fixed (outline->xmax)
- - sfnt_floor_fixed (outline->xmin)) >> 16;
+ - sfnt_floor_fixed (outline->xmin)) / 65536;
raster->height
= (sfnt_ceil_fixed (outline->ymax)
- - sfnt_floor_fixed (outline->ymin)) >> 16;
+ - sfnt_floor_fixed (outline->ymin)) / 65536;
raster->refcount = 0;
/* Align the raster to a SFNT_POLY_ALIGNMENT byte boundary. */
However, variable fonts typically change this as variations are
applied. */
raster->offx = sfnt_floor_fixed (outline->xmin
- - outline->origin) >> 16;
- raster->offy = sfnt_floor_fixed (outline->ymin) >> 16;
+ - outline->origin) / 65536;
+ raster->offy = sfnt_floor_fixed (outline->ymin) / 65536;
}
typedef void (*sfnt_edge_proc) (struct sfnt_edge *, size_t,
#endif
}
-/* Multiply-round the specified two 26.6 fixed point numbers A and B.
+/* Multiply the specified two 26.6 fixed point numbers A and B.
Return the result, or an undefined value upon overflow. */
static sfnt_f26dot6
#endif
}
-#ifndef INT64_MAX
-
-/* 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
-
/* Multiply the specified 26.6 fixed point number X by the specified
16.16 fixed point number Y with symmetric rounding.
for (i = 0; i < glyph->simple->number_of_points; ++i)
{
- fword = sfnt_mul_fixed (dx[i], scale);
+ fword = sfnt_mul_fixed_round (dx[i], scale);
glyph->simple->x_coordinates[i] += fword;
- fword = sfnt_mul_fixed (dy[i], scale);
+ fword = sfnt_mul_fixed_round (dy[i], scale);
glyph->simple->y_coordinates[i] += fword;
}
/* Apply the deltas for the two phantom points. */
- distortion->origin += sfnt_mul_fixed (dx[i++], scale);
- distortion->advance += sfnt_mul_fixed (dx[i], scale);
+ distortion->origin += sfnt_mul_fixed_round (dx[i++], scale);
+ distortion->advance += sfnt_mul_fixed_round (dx[i], scale);
break;
default:
if (glyph_points[i] == glyph->simple->number_of_points)
{
- distortion->origin += sfnt_mul_fixed (dx[i], scale);
+ distortion->origin += sfnt_mul_fixed_round (dx[i], scale);
continue;
}
if (glyph_points[i] == glyph->simple->number_of_points + 1)
{
- distortion->advance += sfnt_mul_fixed (dx[i], scale);
+ distortion->advance += sfnt_mul_fixed_round (dx[i], scale);
continue;
}
if (glyph_points[i] >= glyph->simple->number_of_points)
continue;
- fword = sfnt_mul_fixed (dx[i], scale);
+ fword = sfnt_mul_fixed_round (dx[i], scale);
glyph->simple->x_coordinates[glyph_points[i]] += fword;
- fword = sfnt_mul_fixed (dy[i], scale);
+ fword = sfnt_mul_fixed_round (dy[i], scale);
glyph->simple->y_coordinates[glyph_points[i]] += fword;
touched[glyph_points[i]] = true;
}
else
word = component->argument1.d;
- fword = sfnt_mul_fixed (dx[i], scale);
+ fword = sfnt_mul_fixed_round (dx[i], scale);
component->flags |= 01;
component->argument1.d = word + fword;
else
word = component->argument2.d;
- fword = sfnt_mul_fixed (dy[i], scale);
+ fword = sfnt_mul_fixed_round (dy[i], scale);
component->flags |= 01;
component->argument2.d = word + fword;
}
/* Apply the deltas for the two phantom points. */
- distortion->origin += sfnt_mul_fixed (dx[i++], scale);
- distortion->advance += sfnt_mul_fixed (dx[i], scale);
+ distortion->origin += sfnt_mul_fixed_round (dx[i++], scale);
+ distortion->advance += sfnt_mul_fixed_round (dx[i], scale);
break;
default:
if (glyph_points[i] == glyph->compound->num_components)
{
- distortion->origin += sfnt_mul_fixed (dx[i], scale);
+ distortion->origin += sfnt_mul_fixed_round (dx[i], scale);
continue;
}
if (glyph_points[i] == glyph->compound->num_components + 1)
{
- distortion->advance += sfnt_mul_fixed (dx[i], scale);
+ distortion->advance += sfnt_mul_fixed_round (dx[i], scale);
continue;
}
else
word = component->argument1.d;
- fword = sfnt_mul_fixed (dx[i], scale);
+ fword = sfnt_mul_fixed_round (dx[i], scale);
component->flags |= 01;
component->argument1.d = word + fword;
else
word = component->argument2.d;
- fword = sfnt_mul_fixed (dy[i], scale);
+ fword = sfnt_mul_fixed_round (dy[i], scale);
component->flags |= 01;
component->argument2.d = word + fword;
}
then the tuple scale factor. */
delta = sfnt_mul_f26dot6_fixed (variation->deltas[j] * 64,
interpreter->scale);
- delta = sfnt_mul_fixed (delta, scale);
+ delta = sfnt_mul_fixed_round (delta, scale);
/* Apply the delta to the control value table. */
interpreter->cvt[i] += delta;
return 1;
}
-#define FANCY_PPEM 40
-#define EASY_PPEM 40
+#define FANCY_PPEM 36
+#define EASY_PPEM 36
interpreter = NULL;
head = sfnt_read_head_table (fd, font);
&dcontext))
printf ("decomposition failure\n");
- if (sfnt_lookup_glyph_metrics (code, EASY_PPEM,
+ if (sfnt_lookup_glyph_metrics (code, -1,
&metrics,
hmtx, hhea,
head, maxp))
if (outline)
{
+ fprintf (stderr, "outline origin, rbearing: %"
+ PRIi32" %"PRIi32"\n",
+ outline->origin,
+ outline->ymax - outline->origin);
sfnt_test_max = outline->ymax - outline->ymin;
for (i = 0; i < outline->outline_used; i++)
}
}
- /* At this point, the glyph metrics are unscaled. Scale them up.
- If INTERPRETER is set, use the scale placed within. */
-
- sfnt_scale_metrics (&temp, scale);
-
if (!outline)
{
if (!interpreter)
&dcontext);
}
+ /* At this point, the glyph metrics are unscaled. Scale them up.
+ If INTERPRETER is set, use the scale placed within. */
+
+ sfnt_scale_metrics (&temp, scale);
+
fail:
xfree (glyph);
num_characters++;
/* Add the advance to total_width. */
- total_width += metrics.advance >> 16;
+ total_width += metrics.advance / 65536;
/* Update min_width if it hasn't been set yet or is wider. */
if (font_info->font.min_width == 1
- || font_info->font.min_width > metrics.advance >> 16)
- font_info->font.min_width = metrics.advance >> 16;
+ || font_info->font.min_width > metrics.advance / 65536)
+ font_info->font.min_width = metrics.advance / 65536;
/* If i is the space character, set the space width. Make sure
to round this up. */
if (i == 32)
font_info->font.space_width
- = SFNT_CEIL_FIXED (metrics.advance) >> 16;
+ = SFNT_CEIL_FIXED (metrics.advance) / 65536;
}
/* Now, if characters were found, set average_width. */
ASET (font_object, FONT_SPACING_INDEX,
make_fixnum (desc->spacing));
+ /* Set the font style. */
+
FONT_SET_STYLE (font_object, FONT_WIDTH_INDEX,
make_fixnum (desc->width));
FONT_SET_STYLE (font_object, FONT_WEIGHT_INDEX,
/* Make sure the instance is within range. */
&& instance < desc->tables->fvar->instance_count)
{
- sfnt_init_blend (&font_info->blend, desc->tables->fvar,
- desc->tables->gvar, desc->tables->avar,
- desc->tables->cvar);
+ tem = AREF (desc->instances, instance);
+
+ if (!NILP (tem))
+ {
+ sfnt_init_blend (&font_info->blend, desc->tables->fvar,
+ desc->tables->gvar, desc->tables->avar,
+ desc->tables->cvar);
+
+ /* Copy over the coordinates. */
+ for (i = 0; i < desc->tables->fvar->axis_count; ++i)
+ font_info->blend.coords[i]
+ = desc->tables->fvar->instance[instance].coords[i];
- /* Copy over the coordinates. */
- for (i = 0; i < desc->tables->fvar->axis_count; ++i)
- font_info->blend.coords[i]
- = desc->tables->fvar->instance[instance].coords[i];
+ sfnt_normalize_blend (&font_info->blend);
- sfnt_normalize_blend (&font_info->blend);
+ /* If an interpreter was specified, distort it now. */
- /* If an interpreter was specified, distort it now. */
+ if (font_info->interpreter)
+ sfnt_vary_interpreter (font_info->interpreter,
+ &font_info->blend);
- if (font_info->interpreter)
- sfnt_vary_interpreter (font_info->interpreter,
- &font_info->blend);
+ font_info->instance = instance;
- font_info->instance = instance;
+ /* Replace the style information with that of the
+ instance. */
+
+ FONT_SET_STYLE (font_object, FONT_WIDTH_INDEX,
+ AREF (tem, 2));
+ FONT_SET_STYLE (font_object, FONT_WEIGHT_INDEX,
+ AREF (tem, 3));
+ FONT_SET_STYLE (font_object, FONT_SLANT_INDEX,
+ AREF (tem, 4));
+ ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
+ }
}
#ifdef HAVE_HARFBUZZ
if (!outline)
return 1;
- pcm->lbearing = metrics.lbearing >> 16;
- pcm->rbearing = SFNT_CEIL_FIXED (outline->xmax) >> 16;
+ pcm->lbearing = metrics.lbearing / 65536;
+ pcm->rbearing = SFNT_CEIL_FIXED (outline->xmax) / 65536;
/* Round the advance, ascent and descent upwards. */
- pcm->width = SFNT_CEIL_FIXED (metrics.advance) >> 16;
- pcm->ascent = SFNT_CEIL_FIXED (outline->ymax) >> 16;
- pcm->descent = SFNT_CEIL_FIXED (-outline->ymin) >> 16;
+ pcm->width = SFNT_CEIL_FIXED (metrics.advance) / 65536;
+ pcm->ascent = SFNT_CEIL_FIXED (outline->ymax) / 65536;
+ pcm->descent = SFNT_CEIL_FIXED (-outline->ymin) / 65536;
sfntfont_dereference_outline (outline);
return 0;
if (s->padding_p)
current_x += 1;
else
- current_x += SFNT_CEIL_FIXED (metrics.advance) >> 16;
+ current_x += SFNT_CEIL_FIXED (metrics.advance) / 65536;
}
/* Call the window system function to put the glyphs to the