]> code.delx.au - gnu-emacs/commitdiff
Improve the speedup of bidi display introduced in 2011-10-18T16:56:09Z!eliz@gnu.org...
authorEli Zaretskii <eliz@gnu.org>
Thu, 20 Oct 2011 12:39:52 +0000 (14:39 +0200)
committerEli Zaretskii <eliz@gnu.org>
Thu, 20 Oct 2011 12:39:52 +0000 (14:39 +0200)
 src/dispextern.h (struct bidi_it): New member next_en_type.
 src/bidi.c (bidi_line_init): Initialize the next_en_type member.
 (bidi_resolve_explicit_1): When next_en_pos is valid for the
 current character, check also for next_en_type being WEAK_EN.
 (bidi_resolve_weak): Don't enter the expensive loop if the current
 position is before next_en_pos.  Record the bidi type of the first
 non-ET, non-BN character we find, in addition to its position.
 (bidi_level_of_next_char): Invalidate next_en_type when
 next_en_pos is over-stepped.

src/ChangeLog
src/bidi.c
src/dispextern.h

index 36b205a120d4505d08551263050919183d8f09c8..3f9b5beeab6feed428c5765e0f4b4492f3af6348 100644 (file)
@@ -1,3 +1,16 @@
+2011-10-20  Eli Zaretskii  <eliz@gnu.org>
+
+       * dispextern.h (struct bidi_it): New member next_en_type.
+
+       * bidi.c (bidi_line_init): Initialize the next_en_type member.
+       (bidi_resolve_explicit_1): When next_en_pos is valid for the
+       current character, check also for next_en_type being WEAK_EN.
+       (bidi_resolve_weak): Don't enter the expensive loop if the current
+       position is before next_en_pos.  Record the bidi type of the first
+       non-ET, non-BN character we find, in addition to its position.
+       (bidi_level_of_next_char): Invalidate next_en_type when
+       next_en_pos is over-stepped.
+
 2011-10-20  Paul Eggert  <eggert@cs.ucla.edu>
 
        Time zone name fixes for non-ASCII locales (Bug#641, Bug#9794)
index 29e3c8173187dd92f79a50e738e90ec9baca7d46..d13baed63ed1f41fe27d50b4a3fefc967ef23e2a 100644 (file)
@@ -849,6 +849,7 @@ bidi_line_init (struct bidi_it *bidi_it)
   /* Setting this to zero will force its recomputation the first time
      we need it for W5.  */
   bidi_it->next_en_pos = 0;
+  bidi_it->next_en_type = UNKNOWN_BT;
   bidi_it->next_for_ws.type = UNKNOWN_BT;
   bidi_set_sor_type (bidi_it,
                     (bidi_it->paragraph_dir == R2L ? 1 : 0),
@@ -1437,7 +1438,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
              }
          }
        else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
-                || bidi_it->next_en_pos > bidi_it->charpos)
+                || (bidi_it->next_en_pos > bidi_it->charpos
+                    && bidi_it->next_en_type == WEAK_EN))
          type = WEAK_EN;
        break;
       case LRE:        /* X3 */
@@ -1473,7 +1475,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
              }
          }
        else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
-                || bidi_it->next_en_pos > bidi_it->charpos)
+                || (bidi_it->next_en_pos > bidi_it->charpos
+                    && bidi_it->next_en_type == WEAK_EN))
          type = WEAK_EN;
        break;
       case PDF:        /* X7 */
@@ -1499,7 +1502,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
              }
          }
        else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
-                || bidi_it->next_en_pos > bidi_it->charpos)
+                || (bidi_it->next_en_pos > bidi_it->charpos
+                    && bidi_it->next_en_type == WEAK_EN))
          type = WEAK_EN;
        break;
       default:
@@ -1731,10 +1735,15 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
       else if (type == WEAK_ET /* W5: ET with EN before or after it */
               || type == WEAK_BN)      /* W5/Retaining */
        {
-         if (bidi_it->prev.type_after_w1 == WEAK_EN /* ET/BN w/EN before it */
-             || bidi_it->next_en_pos > bidi_it->charpos)
+         if (bidi_it->prev.type_after_w1 == WEAK_EN) /* ET/BN w/EN before it */
            type = WEAK_EN;
-         else if (bidi_it->next_en_pos >=0) /* W5: ET/BN with EN after it.  */
+         else if (bidi_it->next_en_pos > bidi_it->charpos
+                  && bidi_it->next_en_type != WEAK_BN)
+           {
+             if (bidi_it->next_en_type == WEAK_EN) /* ET/BN with EN after it */
+               type = WEAK_EN;
+           }
+         else if (bidi_it->next_en_pos >=0)
            {
              EMACS_INT en_pos = bidi_it->charpos + bidi_it->nchars;
              const unsigned char *s = (STRINGP (bidi_it->string.lstring)
@@ -1763,25 +1772,27 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
                  en_pos = bidi_it->charpos;
                  bidi_copy_it (bidi_it, &saved_it);
                }
+             /* Remember this position, to speed up processing of the
+                next ETs.  */
+             bidi_it->next_en_pos = en_pos;
              if (type_of_next == WEAK_EN)
                {
                  /* If the last strong character is AL, the EN we've
                     found will become AN when we get to it (W2). */
-                 if (bidi_it->last_strong.type_after_w1 != STRONG_AL)
-                   {
-                     type = WEAK_EN;
-                     /* Remember this EN position, to speed up processing
-                        of the next ETs.  */
-                     bidi_it->next_en_pos = en_pos;
-                   }
+                 if (bidi_it->last_strong.type_after_w1 == STRONG_AL)
+                   type_of_next = WEAK_AN;
                  else if (type == WEAK_BN)
                    type = NEUTRAL_ON; /* W6/Retaining */
+                 else
+                   type = WEAK_EN;
                }
              else if (type_of_next == NEUTRAL_B)
                /* Record the fact that there are no more ENs from
                   here to the end of paragraph, to avoid entering the
                   loop above ever again in this paragraph.  */
                bidi_it->next_en_pos = -1;
+             /* Record the type of the character where we ended our search.  */
+             bidi_it->next_en_type = type_of_next;
            }
        }
     }
@@ -2053,7 +2064,10 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
        bidi_it->next_for_neutral.type = UNKNOWN_BT;
       if (bidi_it->next_en_pos >= 0
          && bidi_it->charpos >= bidi_it->next_en_pos)
-       bidi_it->next_en_pos = 0;
+       {
+         bidi_it->next_en_pos = 0;
+         bidi_it->next_en_type = UNKNOWN_BT;
+       }
       if (bidi_it->next_for_ws.type != UNKNOWN_BT
          && bidi_it->charpos >= bidi_it->next_for_ws.charpos)
        bidi_it->next_for_ws.type = UNKNOWN_BT;
index 3c157371ef37a969d9f06f83739b9a52ada8fb02..dd5f67d2d105f16a8f0239dc29ce43d2cb4a132d 100644 (file)
@@ -1856,7 +1856,8 @@ struct bidi_it {
   struct bidi_saved_info next_for_neutral; /* surrounding characters for... */
   struct bidi_saved_info prev_for_neutral; /* ...resolving neutrals */
   struct bidi_saved_info next_for_ws; /* character after sequence of ws */
-  EMACS_INT next_en_pos;       /* position of next EN char for ET */
+  EMACS_INT next_en_pos;       /* pos. of next char for determining ET type */
+  bidi_type_t next_en_type;    /* type of char at next_en_pos */
   EMACS_INT ignore_bn_limit;   /* position until which to ignore BNs */
   bidi_dir_t sor;              /* direction of start-of-run in effect */
   int scan_dir;                        /* direction of text scan, 1: forw, -1: back */