summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2012-12-21 18:40:08 -0500
committerBehdad Esfahbod <behdad@behdad.org>2012-12-21 18:47:16 -0500
commitb94a519aad3d5b50aa6de47ee16ee6a099de9791 (patch)
treef733f3304cfa28005179ef78a1689e6480b6d29d
parent1404ed9692af1958b4090c46d1a27e0fe4a5616e (diff)
[ft] Fix resizing of bitmap fonts
Say, you were asking cairo for a font at 200px. For bitmap-only fonts, cairo was finding the closes strike size and using it. If the strike was at 20px, well, that's what you were getting. We now scale that 20px strike by a factor of 10 to get the correct size rendering. Note that by itself this patch doesn't change much on the Linux desktop. The reason is that the size you are interested in (eg. 200px) is lost by fontconfig. When you request a font at 200px, fontconfig returns a font pattern that says 20px, and so the next layers thing you want a font at 20px. To address that, one also needs a piece of fontconfig config that puts the 200 back into the pixelsize. Something like this: <match target="font"> <test name="scalable" mode="eq"> <bool>false</bool> </test> <edit name="pixelsize" mode="assign"> <times> <name>size</name> <name>dpi</name> <double>0.0138888888888</double> <!--1/72.--> </times> </edit> </match> I'm going to try to upstream this config so it will be enabled by default. The config can be a bit smarter. For example, if metricshinting is enabled and the size difference is small, we may as well not scale. The nice thing about this is that the configuration of whether and when to scale bitmaps will be done in fontconfig, not cairo / Qt / ... code.
-rw-r--r--src/cairo-ft-font.c66
1 files changed, 34 insertions, 32 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 0580faca2..8ebadb438 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -708,7 +708,8 @@ _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
static cairo_status_t
_compute_transform (cairo_ft_font_transform_t *sf,
- cairo_matrix_t *scale)
+ cairo_matrix_t *scale,
+ cairo_ft_unscaled_font_t *unscaled)
{
cairo_status_t status;
double x_scale, y_scale;
@@ -736,6 +737,30 @@ _compute_transform (cairo_ft_font_transform_t *sf,
if (y_scale < 1.0)
y_scale = 1.0;
+ if (unscaled && (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) {
+ double min_distance = DBL_MAX;
+ int i;
+ int best_i = 0;
+ double best_x_size = 0;
+ double best_y_size = 0;
+
+ for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
+ double x_size = unscaled->face->available_sizes[i].y_ppem / 64.;
+ double y_size = unscaled->face->available_sizes[i].y_ppem / 64.;
+ double distance = fabs (y_size - y_scale);
+
+ if (distance <= min_distance) {
+ min_distance = distance;
+ best_i = i;
+ best_x_size = x_size;
+ best_y_size = y_size;
+ }
+ }
+
+ x_scale = best_x_size;
+ y_scale = best_y_size;
+ }
+
sf->x_scale = x_scale;
sf->y_scale = y_scale;
@@ -773,7 +798,7 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
unscaled->have_scale = TRUE;
unscaled->current_scale = *scale;
- status = _compute_transform (&sf, scale);
+ status = _compute_transform (&sf, scale, unscaled);
if (unlikely (status))
return status;
@@ -798,35 +823,12 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
FT_Set_Transform(unscaled->face, &mat, NULL);
- if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
- error = FT_Set_Char_Size (unscaled->face,
- sf.x_scale * 64.0 + .5,
- sf.y_scale * 64.0 + .5,
- 0, 0);
- if (error)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- } else {
- double min_distance = DBL_MAX;
- int i;
- int best_i = 0;
-
- for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
- double size = unscaled->face->available_sizes[i].y_ppem / 64.;
- double distance = fabs (size - sf.y_scale);
-
- if (distance <= min_distance) {
- min_distance = distance;
- best_i = i;
- }
- }
- error = FT_Set_Char_Size (unscaled->face,
- unscaled->face->available_sizes[best_i].x_ppem,
- unscaled->face->available_sizes[best_i].y_ppem,
- 0, 0);
-
- if (error)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
+ error = FT_Set_Char_Size (unscaled->face,
+ sf.x_scale * 64.0 + .5,
+ sf.y_scale * 64.0 + .5,
+ 0, 0);
+ if (error)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
@@ -3079,7 +3081,7 @@ _cairo_ft_resolve_pattern (FcPattern *pattern,
font_matrix,
&scale);
- status = _compute_transform (&sf, &scale);
+ status = _compute_transform (&sf, &scale, NULL);
if (unlikely (status))
return (cairo_font_face_t *)&_cairo_font_face_nil;