freetype-commit
[Top][All Lists]
Advanced

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

[freetype2] master 3fa5c8456: [raster] Fix linked profiles in contour lo


From: Werner Lemberg
Subject: [freetype2] master 3fa5c8456: [raster] Fix linked profiles in contour loops.
Date: Wed, 18 Oct 2023 00:16:58 -0400 (EDT)

branch: master
commit 3fa5c84565f2431a13247f055623508137dc5739
Author: Alexei Podtelezhnikov <apodtele@gmail.com>
Commit: Alexei Podtelezhnikov <apodtele@gmail.com>

    [raster] Fix linked profiles in contour loops.
    
    This fixes a subtle bug when the last profile in a contour was not
    properly short-circuited if it was still empty at `End_Profile`.
    We finalize all linking in `Finalize_Profile_List` now and do nothing
    else there.  The turns are added in `End_Profile`.
    
    * src/raster/ftraster.c (Insert_Y_Turn): Moved up unchanged.
    (End_Profile): Take care of turns but set only preliminary linking.
    (Finalize_Profile_Table): Take care of linking and null-termination.
    (Convert_Glyph): Adjusted accordingly.
---
 src/raster/ftraster.c | 214 ++++++++++++++++++++++++--------------------------
 1 file changed, 101 insertions(+), 113 deletions(-)

diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index 55a24d73e..7991bb118 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -591,6 +591,62 @@
   }
 
 
+  /**************************************************************************
+   *
+   * @Function:
+   *   Insert_Y_Turn
+   *
+   * @Description:
+   *   Insert a salient into the sorted list placed on top of the render
+   *   pool.
+   *
+   * @Input:
+   *   New y scanline position.
+   *
+   * @Return:
+   *   SUCCESS on success.  FAILURE in case of overflow.
+   */
+  static Bool
+  Insert_Y_Turn( RAS_ARGS Int  y )
+  {
+    PLong  y_turns;
+    Int    n;
+
+
+    n       = ras.numTurns - 1;
+    y_turns = ras.sizeBuff - ras.numTurns;
+
+    /* look for first y value that is <= */
+    while ( n >= 0 && y < y_turns[n] )
+      n--;
+
+    /* if it is <, simply insert it, ignore if == */
+    if ( n >= 0 && y > y_turns[n] )
+      do
+      {
+        Int  y2 = (Int)y_turns[n];
+
+
+        y_turns[n] = y;
+        y = y2;
+      } while ( --n >= 0 );
+
+    if ( n < 0 )
+    {
+      ras.maxBuff--;
+      if ( ras.maxBuff <= ras.top )
+      {
+        ras.error = FT_THROW( Raster_Overflow );
+        return FAILURE;
+      }
+      ras.numTurns++;
+      ras.sizeBuff[-ras.numTurns] = y;
+    }
+
+    return SUCCESS;
+  }
+
+
   /**************************************************************************
    *
    * @Function:
@@ -687,10 +743,10 @@
   static Bool
   End_Profile( RAS_ARGS Bool  overshoot )
   {
-    Long  h;
-
+    PProfile  p = ras.cProfile;
+    Long      h = (Long)( ras.top - p->offset );
+    Int       bottom, top;
 
-    h = (Long)( ras.top - ras.cProfile->offset );
 
     if ( h < 0 )
     {
@@ -701,82 +757,45 @@
 
     if ( h > 0 )
     {
-      FT_TRACE7(( "  ending profile %p, start = %ld, height = %ld\n",
-                  (void *)ras.cProfile, ras.cProfile->start, h ));
+      FT_TRACE7(( "  ending profile %p, start = %2ld, height = %+3ld\n",
+                  (void *)p, p->start, p->flags & Flow_Up ? h : -h ));
 
-      ras.cProfile->height = h;
       if ( overshoot )
       {
-        if ( ras.cProfile->flags & Flow_Up )
-          ras.cProfile->flags |= Overshoot_Top;
+        if ( p->flags & Flow_Up )
+          p->flags |= Overshoot_Top;
         else
-          ras.cProfile->flags |= Overshoot_Bottom;
+          p->flags |= Overshoot_Bottom;
       }
 
-      /* premature, the last profile in the contour must loop */
-      ras.cProfile->next = (PProfile)ras.top;
-
-      ras.num_Profs++;
-    }
-
-    ras.joint = FALSE;
-
-    return SUCCESS;
-  }
-
+      p->height = h;
 
-  /**************************************************************************
-   *
-   * @Function:
-   *   Insert_Y_Turn
-   *
-   * @Description:
-   *   Insert a salient into the sorted list placed on top of the render
-   *   pool.
-   *
-   * @Input:
-   *   New y scanline position.
-   *
-   * @Return:
-   *   SUCCESS on success.  FAILURE in case of overflow.
-   */
-  static Bool
-  Insert_Y_Turn( RAS_ARGS Int  y )
-  {
-    PLong  y_turns;
-    Int    n;
-
-
-    n       = ras.numTurns - 1;
-    y_turns = ras.sizeBuff - ras.numTurns;
-
-    /* look for first y value that is <= */
-    while ( n >= 0 && y < y_turns[n] )
-      n--;
-
-    /* if it is <, simply insert it, ignore if == */
-    if ( n >= 0 && y > y_turns[n] )
-      do
+      if ( p->flags & Flow_Up )
       {
-        Int  y2 = (Int)y_turns[n];
+        bottom = (Int)p->start;
+        top    = (Int)( p->start + h - 1 );
+      }
+      else
+      {
+        bottom     = (Int)( p->start - h + 1 );
+        top        = (Int)p->start;
+        p->start   = bottom;
+        p->offset += h - 1;
+      }
 
+      if ( Insert_Y_Turn( RAS_VARS bottom )  ||
+           Insert_Y_Turn( RAS_VARS top + 1 ) )
+        return FAILURE;
 
-        y_turns[n] = y;
-        y = y2;
-      } while ( --n >= 0 );
+      /* preliminary values to be finalized */
+      p->link = (PProfile)ras.top;
+      p->next = ras.gProfile;
 
-    if ( n < 0 )
-    {
-      ras.maxBuff--;
-      if ( ras.maxBuff <= ras.top )
-      {
-        ras.error = FT_THROW( Raster_Overflow );
-        return FAILURE;
-      }
-      ras.numTurns++;
-      ras.sizeBuff[-ras.numTurns] = y;
+      ras.num_Profs++;
     }
 
+    ras.joint = FALSE;
+
     return SUCCESS;
   }
 
@@ -788,56 +807,28 @@
    *
    * @Description:
    *   Adjust all links in the profiles list.
-   *
-   * @Return:
-   *   SUCCESS on success.  FAILURE in case of overflow.
    */
-  static Bool
+  static void
   Finalize_Profile_Table( RAS_ARG )
   {
-    UShort    n;
-    PProfile  p;
-
+    UShort    n = ras.num_Profs;
+    PProfile  p = ras.fProfile;
+    PProfile  q;
 
-    n = ras.num_Profs;
-    p = ras.fProfile;
 
-    if ( n > 1 && p )
+    while ( --n )
     {
-      do
-      {
-        Int  bottom, top;
-
-
-        if ( n > 1 )
-          p->link = (PProfile)( p->offset + p->height );
-        else
-          p->link = NULL;
-
-        if ( p->flags & Flow_Up )
-        {
-          bottom = (Int)p->start;
-          top    = (Int)( p->start + p->height - 1 );
-        }
-        else
-        {
-          bottom     = (Int)( p->start - p->height + 1 );
-          top        = (Int)p->start;
-          p->start   = bottom;
-          p->offset += p->height - 1;
-        }
+      q = p->link;
 
-        if ( Insert_Y_Turn( RAS_VARS bottom )  ||
-             Insert_Y_Turn( RAS_VARS top + 1 ) )
-          return FAILURE;
+      /* fix the contour loop */
+      if ( q->next == p->next )
+        p->next = q;
 
-        p = p->link;
-      } while ( --n );
+      p = q;
     }
-    else
-      ras.fProfile = NULL;
 
-    return SUCCESS;
+    /* null-terminate */
+    p->link = NULL;
   }
 
 
@@ -2001,17 +1992,14 @@
       if ( End_Profile( RAS_VARS o ) )
         return FAILURE;
 
-      /* loop the last profile in the contour */
-      ras.cProfile->next = ras.gProfile;
-
-      if ( !ras.fProfile )
+      if ( !ras.fProfile && ras.num_Profs )
         ras.fProfile = ras.gProfile;
     }
 
-    if ( Finalize_Profile_Table( RAS_VAR ) )
-      return FAILURE;
+    if ( ras.num_Profs )
+      Finalize_Profile_Table( RAS_VAR );
 
-    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+    return SUCCESS;
   }
 
 



reply via email to

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