[pango: 5/6] font-desc: Use local volatile double values to store sizes




commit d439eea5909b13a138930a668b3114a1dc4904b4
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Tue Jul 13 21:08:31 2021 +0200

    font-desc: Use local volatile double values to store sizes
    
    Under i386 multiplying double and integer values and cast it to integer
    may end up to compute the wrong value when only 387 FPU is used, because
    the temporary value will be stored in a register whose precision isn't
    good enough.
    And so, some multiplications which are expected to produce an integer,
    will actually return a truncated value, that will be eventually floored.
    
    An example is 1.2 * 12800 that is clearly 15360.0, but will produce
    15359 when casted to int in the said i386 environment.
    
    So use a temporary double variable to ensure that we do this computation
    in the double scope, before casting to int.
    
    And this will avoid using the said register, even when using more
    aggressive optimizations (as per marking the local variable volatile).
    
    Fixes: https://gitlab.gnome.org/GNOME/pango/-/issues/580

 pango/pango-attributes.c | 10 ++++++++--
 pango/pango-markup.c     | 16 ++++++++++------
 pango/pangofc-fontmap.c  |  8 +++++++-
 3 files changed, 25 insertions(+), 9 deletions(-)
---
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index fd0df205..26d08404 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -2382,10 +2382,16 @@ pango_attr_iterator_get_font (PangoAttrIterator     *iterator,
 
   if (have_scale)
     {
+      /* We need to use a local variable to ensure that the compiler won't
+       * implicitly cast it to integer while the result is kept in registers,
+       * leading to a wrong approximation in i386 (with 387 FPU)
+       */
+      volatile double size = scale * pango_font_description_get_size (desc);
+
       if (pango_font_description_get_size_is_absolute (desc))
-        pango_font_description_set_absolute_size (desc, scale * pango_font_description_get_size (desc));
+        pango_font_description_set_absolute_size (desc, size);
       else
-        pango_font_description_set_size (desc, scale * pango_font_description_get_size (desc));
+        pango_font_description_set_size (desc, size);
     }
 }
 
diff --git a/pango/pango-markup.c b/pango/pango-markup.c
index 38e908c5..2828eab3 100644
--- a/pango/pango-markup.c
+++ b/pango/pango-markup.c
@@ -294,12 +294,16 @@ markup_data_close_tag (MarkupData *md)
 
       if (ot->has_base_font_size)
        {
-         /* Create a font using the absolute point size
-          * as the base size to be scaled from
-          */
-         a = pango_attr_size_new (scale_factor (ot->scale_level,
-                                                1.0) *
-                                  ot->base_font_size);
+          /* Create a font using the absolute point size as the base size
+           * to be scaled from.
+           * We need to use a local variable to ensure that the compiler won't
+           * implicitly cast it to integer while the result is kept in registers,
+           * leading to a wrong approximation in i386 (with 387 FPU)
+           */
+          volatile double size;
+
+          size = scale_factor (ot->scale_level, 1.0) * ot->base_font_size;
+          a = pango_attr_size_new (size);
        }
       else
        {
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index 62f2cd4b..9c008411 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -2789,6 +2789,7 @@ pango_fc_font_description_from_pattern (FcPattern *pattern, gboolean include_siz
     {
       FcMatrix *fc_matrix;
       double scale_factor = 1;
+      volatile double scaled_size;
 
       if (FcPatternGetMatrix (pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
         {
@@ -2802,7 +2803,12 @@ pango_fc_font_description_from_pattern (FcPattern *pattern, gboolean include_siz
           scale_factor = pango_matrix_get_font_scale_factor (&mat);
         }
 
-      pango_font_description_set_size (desc, scale_factor * size * PANGO_SCALE);
+      /* We need to use a local variable to ensure that the compiler won't
+       * implicitly cast it to integer while the result is kept in registers,
+       * leading to a wrong approximation in i386 (with 387 FPU)
+       */
+      scaled_size = scale_factor * size * PANGO_SCALE;
+      pango_font_description_set_size (desc, scaled_size);
     }
 
   /* gravity is a bit different.  we don't want to set it if it was not set on


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]