1
1
// Copyright 2022 the Resvg Authors
2
2
// SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
4
- use std:: collections:: HashMap ;
4
+ use std:: collections:: { HashMap , HashSet } ;
5
5
use std:: num:: NonZeroU16 ;
6
6
use std:: sync:: Arc ;
7
7
@@ -882,6 +882,11 @@ fn process_chunk(
882
882
// but some can use `fi` (U+FB01) instead.
883
883
// Meaning that during merging we have to overwrite not individual glyphs, but clusters.
884
884
885
+ // Glyph splitting assigns distinct glyphs to the same index in the original text, we need to
886
+ // store previously used indices to make sure we do not re-use the same index while overwriting
887
+ // span glyphs.
888
+ let mut positions = HashSet :: new ( ) ;
889
+
885
890
let mut glyphs = Vec :: new ( ) ;
886
891
for span in & chunk. spans {
887
892
let font = match fonts_cache. get ( & span. font ) {
@@ -904,17 +909,25 @@ fn process_chunk(
904
909
continue ;
905
910
}
906
911
912
+ positions. clear ( ) ;
913
+
907
914
// Overwrite span's glyphs.
908
915
let mut iter = tmp_glyphs. into_iter ( ) ;
909
916
while let Some ( new_glyph) = iter. next ( ) {
910
917
if !span_contains ( span, new_glyph. byte_idx ) {
911
918
continue ;
912
919
}
913
920
914
- let Some ( idx) = glyphs. iter ( ) . position ( |g| g. byte_idx == new_glyph. byte_idx ) else {
921
+ let Some ( idx) = glyphs
922
+ . iter ( )
923
+ . position ( |g| g. byte_idx == new_glyph. byte_idx )
924
+ . filter ( |pos| !positions. contains ( pos) )
925
+ else {
915
926
continue ;
916
927
} ;
917
928
929
+ positions. insert ( idx) ;
930
+
918
931
let prev_cluster_len = glyphs[ idx] . cluster_len ;
919
932
if prev_cluster_len < new_glyph. cluster_len {
920
933
// If the new font represents the same cluster with fewer glyphs
0 commit comments