freetype-commit
[Top][All Lists]
Advanced

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

[freetype2-demos] master 616e025 3/3: [ftgrid] Implement reversible floa


From: Alexei Podtelezhnikov
Subject: [freetype2-demos] master 616e025 3/3: [ftgrid] Implement reversible floating zoom.
Date: Tue, 29 Sep 2020 09:12:18 -0400 (EDT)

branch: master
commit 616e025ad5dbb97890bd2cd93f400a266b0ec52b
Author: Alexei Podtelezhnikov <apodtele@gmail.com>
Commit: Alexei Podtelezhnikov <apodtele@gmail.com>

    [ftgrid] Implement reversible floating zoom.
    
    The floating zoom is neccessary to display extremely large sizes
    after scaling them down, but it has to stay rounded to integers when
    displaying grids and bitmaps for small sizes. All this can be
    achievied by truncating and bit-adjusting numbers in IEEE 754 format.
    To make it portable too, we rely on C99 `frexpf' and `ldexpf'.
    
    * src/ftgid.c (status): Change type of `scale'.
    (ZOOM, grid_status_init, grid_status_rescale,
    grid_status_draw_{grid,outline}): Updated accordingly.
    (event_grid_zoom): Implement truncated reversible zoom.
---
 ChangeLog    | 15 ++++++++++++++
 src/ftgrid.c | 64 ++++++++++++++++++++++++++++++++++--------------------------
 2 files changed, 51 insertions(+), 28 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 253e94b..b4cb035 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2020-09-29  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [ftgrid] Implement reversible floating zoom.
+
+       The floating zoom is neccessary to display extremely large sizes
+       after scaling them down, but it has to stay rounded to integers when
+       displaying grids and bitmaps for small sizes. All this can be
+       achievied by truncating and bit-adjusting numbers in IEEE 754 format.
+       To make it portable too, we rely on C99 `frexpf' and `ldexpf'.
+
+       * src/ftgid.c (status): Change type of `scale'.
+       (ZOOM, grid_status_init, grid_status_rescale,
+       grid_status_draw_{grid,outline}): Updated accordingly.
+       (event_grid_zoom): Implement truncated reversible zoom.
+
 2020-09-28  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        * src/ftgrid.c (ZOOM, *): Macro to zoom metrics.
diff --git a/src/ftgrid.c b/src/ftgrid.c
index 9b92400..0af226d 100644
--- a/src/ftgrid.c
+++ b/src/ftgrid.c
@@ -18,6 +18,7 @@
 #include "output.h"
 #include "mlgetopt.h"
 #include <stdlib.h>
+#include <math.h>
 
   /* the following header shouldn't be used in normal programs */
 #include <freetype/internal/ftdebug.h>
@@ -94,7 +95,7 @@
 #define DO_DOTS         8
 #define DO_DOTNUMBERS  16
 
-#define ZOOM( x )  ( ( (x) * st->scale ) >> 6 )
+#define ZOOM( x )  ( (FT_Pos)( (x) * st->scale ) >> 6 )
 
   typedef struct  GridStatusRec_
   {
@@ -107,11 +108,11 @@
     int          Num;  /* glyph index */
     int          font_index;
 
-    int          scale;
+    float        scale;
     int          x_origin;
     int          y_origin;
 
-    int          scale_0;
+    float        scale_0;
     int          x_origin_0;
     int          y_origin_0;
 
@@ -174,7 +175,7 @@
     st->device        = NULL;  /* default */
     st->res           = 72;
 
-    st->scale         = 64;
+    st->scale         = 64.0f;
     st->x_origin      = 0;
     st->y_origin      = 0;
 
@@ -242,10 +243,10 @@
   {
     int  x_org   = st->x_origin;
     int  y_org   = st->y_origin;
-    int  xy_incr = st->scale;
+    int  xy_incr = (int)st->scale;
 
 
-    if ( xy_incr >= 2 )
+    if ( xy_incr >= 4 )
     {
       int  x2 = x_org;
       int  y2 = y_org;
@@ -530,7 +531,7 @@
     FT_Size       size;
     FT_GlyphSlot  slot;
     FT_UInt       glyph_idx;
-    int           scale = st->scale;
+    int           scale = (int)st->scale;
     int           ox    = st->x_origin;
     int           oy    = st->y_origin;
 
@@ -579,7 +580,7 @@
     }
 
     /* render scaled bitmap */
-    if ( st->work & DO_BITMAP )
+    if ( st->work & DO_BITMAP && scale == st->scale )
     {
       FT_Glyph        glyph, glyf;
       int             left, top, x_advance, y_advance;
@@ -627,8 +628,8 @@
 
 
         /* half-pixel shift hints the stroked path */
-        vec->x = vec->x * scale + 32;
-        vec->y = vec->y * scale - 32;
+        vec->x = (FT_Pos)( vec->x * st->scale ) + 32;
+        vec->y = (FT_Pos)( vec->y * st->scale ) - 32;
       }
 
       /* stroke then draw it */
@@ -1123,20 +1124,23 @@
 
 
   static void
-  event_grid_zoom( double  zoom )
+  event_grid_zoom( int  step )
   {
-    int  scale_old = status.scale;
+    int  frc, exp;
 
+    /* The floating scale is reversibly adjusted after decomposing it into */
+    /* fraction and exponent. Direct bit manipulation is less portable.    */
+    frc = 8 * frexpf( status.scale, &exp );
 
-    status.scale *= zoom;
+    frc  = ( frc & 3 ) | ( exp << 2 );
+    frc += step;
+    exp  = frc >> 2;
+    frc  = ( frc & 3 ) | 4;
 
-    /* avoid same zoom value due to truncation */
-    /* to integer in above multiplication      */
-    if ( status.scale == scale_old && zoom > 1.0 )
-      status.scale++;
+    status.scale = ldexpf( frc / 8.0f, exp );
 
     snprintf( status.header_buffer, sizeof ( status.header_buffer ),
-              "zoom scale %d:1", status.scale );
+              "zoom scale %g", status.scale );
 
     status.header = (const char *)status.header_buffer;
   }
@@ -1334,33 +1338,37 @@
       int  xmax = size->metrics.max_advance;
       int  ymax = size->metrics.ascender;
 
-      FT_F26Dot6  x_scale, y_scale;
+      float  x_scale, y_scale;
 
 
       if ( ymax < size->metrics.y_ppem << 6 )
         ymax = size->metrics.y_ppem << 6;
 
       if ( xmax - xmin )
-        x_scale = st->disp_width  * ( 64 - 2 * margin ) / ( xmax - xmin );
+        x_scale = st->disp_width  * ( 64.0f - 2 * margin ) / ( xmax - xmin );
       else
-        x_scale = 64;
+        x_scale = 64.0f;
 
       if ( ymax - ymin )
-        y_scale = st->disp_height * ( 64 - 2 * margin ) / ( ymax - ymin );
+        y_scale = st->disp_height * ( 64.0f - 2 * margin ) / ( ymax - ymin );
       else
-        y_scale = 64;
+        y_scale = 64.0f;
 
       if ( x_scale <= y_scale )
         st->scale = x_scale;
       else
         st->scale = y_scale;
 
-      st->x_origin = 32 * st->disp_width  - ( xmax + xmin ) * st->scale / 2;
-      st->y_origin = 32 * st->disp_height + ( ymax + ymin ) * st->scale / 2;
+      event_grid_zoom( 0 );
+
+      st->x_origin = 32 * st->disp_width  -
+                     (FT_Pos)( ( xmax + xmin ) * st->scale ) / 2;
+      st->y_origin = 32 * st->disp_height +
+                     (FT_Pos)( ( ymax + ymin ) * st->scale ) / 2;
     }
     else
     {
-      st->scale    = 64;
+      st->scale    = 64.0f;
       st->x_origin = st->disp_width  * margin;
       st->y_origin = st->disp_height * ( 64 - margin );
     }
@@ -1683,8 +1691,8 @@
     case grKEY( 'j' ):  event_grid_translate( -1,  0 ); break;
     case grKEY( 'l' ):  event_grid_translate(  1,  0 ); break;
 
-    case grKeyPageUp:   event_grid_zoom( 1.25     ); break;
-    case grKeyPageDown: event_grid_zoom( 1 / 1.25 ); break;
+    case grKeyPageUp:   event_grid_zoom(  1 ); break;
+    case grKeyPageDown: event_grid_zoom( -1 ); break;
 
     case grKeyF2:       if ( status.mm )
                         {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]