diff options
| author | Eli Zaretskii | 2016-03-06 18:14:46 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-03-06 18:14:46 +0200 |
| commit | cc057e43130780e566f4b901a59a88edb3f5130d (patch) | |
| tree | 085a5bb85eb5a019f8d17a837a6110ff58a3ab55 /src | |
| parent | e51b27ec2ce214ef3d8377a27ee9d857bcc66afc (diff) | |
| download | emacs-cc057e43130780e566f4b901a59a88edb3f5130d.tar.gz emacs-cc057e43130780e566f4b901a59a88edb3f5130d.zip | |
Speed up redisplay of binary files with long series of nulls
* src/bidi.c (bidi_resolve_weak): Avoid entering a loop searching
for a character needed for resolving the type of a series of BN
and ET characters, as required by rule W5 of UAX#9, if the results
of the resolution are known in advance, because we are at level
zero, and the previous strong character was L.
(bidi_resolve_neutral): Partially resurrect the optimization for a
long series of control characters in an otherwise strictly L2R
text.
(bidi_level_of_next_char): Don't enter the loop that searches for
a paragraph separator if the current character is already at base
embedding level. (Bug#22739)
Diffstat (limited to 'src')
| -rw-r--r-- | src/bidi.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/src/bidi.c b/src/bidi.c index e7787054e23..9797517e420 100644 --- a/src/bidi.c +++ b/src/bidi.c | |||
| @@ -2318,7 +2318,31 @@ bidi_resolve_weak (struct bidi_it *bidi_it) | |||
| 2318 | if (bidi_it->next_en_type == WEAK_EN) /* ET/BN with EN after it */ | 2318 | if (bidi_it->next_en_type == WEAK_EN) /* ET/BN with EN after it */ |
| 2319 | type = WEAK_EN; | 2319 | type = WEAK_EN; |
| 2320 | } | 2320 | } |
| 2321 | else if (bidi_it->next_en_pos >=0) | 2321 | else if (type == WEAK_BN |
| 2322 | /* This condition is for the following important case: | ||
| 2323 | |||
| 2324 | . we are at level zero | ||
| 2325 | . either previous strong character was L, | ||
| 2326 | or we've seen no strong characters since sos | ||
| 2327 | and the base paragraph direction is L2R | ||
| 2328 | . this BN is NOT a bidi directional control | ||
| 2329 | |||
| 2330 | For such a situation, either this BN will be | ||
| 2331 | converted to EN per W5, and then to L by virtue | ||
| 2332 | of W7; or it will become ON per W6, and then L | ||
| 2333 | because of N1/N2. So we take a shortcut here | ||
| 2334 | and make it L right away, to avoid the | ||
| 2335 | potentially costly loop below. This is | ||
| 2336 | important when the buffer has a long series of | ||
| 2337 | control characters, like binary nulls, and no | ||
| 2338 | R2L characters at all. */ | ||
| 2339 | && new_level == 0 | ||
| 2340 | && !bidi_explicit_dir_char (bidi_it->ch) | ||
| 2341 | && ((bidi_it->last_strong.type == STRONG_L) | ||
| 2342 | || (bidi_it->last_strong.type == UNKNOWN_BT | ||
| 2343 | && bidi_it->sos == L2R))) | ||
| 2344 | type = STRONG_L; | ||
| 2345 | else if (bidi_it->next_en_pos >= 0) | ||
| 2322 | { | 2346 | { |
| 2323 | /* We overstepped the last known position for ET | 2347 | /* We overstepped the last known position for ET |
| 2324 | resolution but there could be other such characters | 2348 | resolution but there could be other such characters |
| @@ -2981,9 +3005,10 @@ bidi_resolve_neutral (struct bidi_it *bidi_it) | |||
| 2981 | entering the expensive loop in the "else" clause. */ | 3005 | entering the expensive loop in the "else" clause. */ |
| 2982 | else if (current_level == 0 | 3006 | else if (current_level == 0 |
| 2983 | && bidi_it->prev_for_neutral.type == STRONG_L | 3007 | && bidi_it->prev_for_neutral.type == STRONG_L |
| 2984 | && type != WEAK_BN | 3008 | && (ASCII_CHAR_P (bidi_it->ch) |
| 2985 | && !bidi_explicit_dir_char (bidi_it->ch) | 3009 | || (type != WEAK_BN |
| 2986 | && !bidi_isolate_fmt_char (type)) | 3010 | && !bidi_explicit_dir_char (bidi_it->ch) |
| 3011 | && !bidi_isolate_fmt_char (type)))) | ||
| 2987 | type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, | 3012 | type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type, |
| 2988 | STRONG_L, current_level); | 3013 | STRONG_L, current_level); |
| 2989 | else if (/* current level is 1 */ | 3014 | else if (/* current level is 1 */ |
| @@ -3163,7 +3188,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 3163 | } | 3188 | } |
| 3164 | } | 3189 | } |
| 3165 | 3190 | ||
| 3166 | /* Perhaps the character we want is already cached s fully resolved. | 3191 | /* Perhaps the character we want is already cached as fully resolved. |
| 3167 | If it is, the call to bidi_cache_find below will return a type | 3192 | If it is, the call to bidi_cache_find below will return a type |
| 3168 | other than UNKNOWN_BT. */ | 3193 | other than UNKNOWN_BT. */ |
| 3169 | if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt) | 3194 | if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt) |
| @@ -3223,7 +3248,10 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 3223 | if ((bidi_it->orig_type == NEUTRAL_WS | 3248 | if ((bidi_it->orig_type == NEUTRAL_WS |
| 3224 | || bidi_it->orig_type == WEAK_BN | 3249 | || bidi_it->orig_type == WEAK_BN |
| 3225 | || bidi_isolate_fmt_char (bidi_it->orig_type)) | 3250 | || bidi_isolate_fmt_char (bidi_it->orig_type)) |
| 3226 | && bidi_it->next_for_ws.charpos < bidi_it->charpos) | 3251 | && bidi_it->next_for_ws.charpos < bidi_it->charpos |
| 3252 | /* If this character is already at base level, we don't need to | ||
| 3253 | reset it, so avoid the potentially costly loop below. */ | ||
| 3254 | && level != bidi_it->level_stack[0].level) | ||
| 3227 | { | 3255 | { |
| 3228 | int ch; | 3256 | int ch; |
| 3229 | ptrdiff_t clen = bidi_it->ch_len; | 3257 | ptrdiff_t clen = bidi_it->ch_len; |