@@ -71,7 +71,6 @@ private static NameRecord[] CloneRecords(NameRecord[] source)
7171 return copy ;
7272 }
7373
74-
7574 internal override void SerializeInternal ( FontsBinaryWriter writer , FontSerializationContext context )
7675 {
7776 // Step 1: Write header
@@ -83,9 +82,9 @@ internal override void SerializeInternal(FontsBinaryWriter writer, FontSerializa
8382 writer . WriteUInt16BigEndian ( count ) ;
8483 writer . WriteUInt16BigEndian ( stringOffset ) ;
8584
86-
87- // Step 2: Prepare string data with deduplication
85+ // Step 2: Prepare string data with ENCODING-AWARE deduplication
8886 var stringData = new List < byte > ( ) ;
87+ // FIX: Include encoding in the key to avoid collisions between different encodings
8988 var stringOffsetMap = new Dictionary < string , ushort > ( ) ;
9089
9190 foreach ( var record in NameRecords )
@@ -94,18 +93,21 @@ internal override void SerializeInternal(FontsBinaryWriter writer, FontSerializa
9493 var str = record . Name ?? string . Empty ;
9594 var encoded = encoding . GetBytes ( str ) ;
9695
97- if ( ! stringOffsetMap . TryGetValue ( str , out var offset ) )
96+ // FIX: Create a unique key that includes both the text AND the encoding
97+ // This ensures that "Aptos Narrow" in ISO-8859-1 and UTF-16BE get different offsets
98+ string dedupKey = $ "{ str } |{ encoding . CodePage } ";
99+
100+ if ( ! stringOffsetMap . TryGetValue ( dedupKey , out var offset ) )
98101 {
99102 offset = ( ushort ) stringData . Count ;
100- stringOffsetMap [ str ] = offset ;
103+ stringOffsetMap [ dedupKey ] = offset ;
101104 stringData . AddRange ( encoded ) ;
102105 }
103106
104107 record . length = ( ushort ) encoded . Length ;
105108 record . offset = offset ;
106109 }
107110
108-
109111 // Step 3: Write NameRecords
110112 foreach ( var record in NameRecords )
111113 {
@@ -116,24 +118,99 @@ internal override void SerializeInternal(FontsBinaryWriter writer, FontSerializa
116118 writer . Write ( stringData . ToArray ( ) ) ;
117119 }
118120
121+ // ALSO UPDATE GetEncodingForRecord() TO RESPECT encodingId:
119122 private static Encoding GetEncodingForRecord ( NameRecord record )
120123 {
121- // Windows / Unicode – alltid säkert
122- if ( record . platformId == 3 || record . platformId == 0 )
124+ // Unicode platform
125+ if ( record . platformId == 0 )
126+ {
123127 return Encoding . BigEndianUnicode ; // UTF-16BE
128+ }
124129
125- // Macintosh – platformId == 1
130+ // Macintosh platform
126131 if ( record . platformId == 1 )
127132 {
128- // MacRoman (codepage 10000) finns inte i .NET 3.5 → fallback till ISO-8859-1
129- // Skillnaden är minimal för västerländska typsnitt – alla vanliga tecken är identiska
130- return Encoding . GetEncoding ( "ISO-8859-1" ) ;
133+ // encodingId 0 = MacRoman (single-byte)
134+ // .NET doesn't have MacRoman (codepage 10000) in all versions
135+ // Fallback to ISO-8859-1 (Latin-1)
136+ try
137+ {
138+ return Encoding . GetEncoding ( "ISO-8859-1" ) ;
139+ }
140+ catch
141+ {
142+ return Encoding . UTF8 ;
143+ }
144+ }
145+
146+ // Windows platform - CRITICAL: Must respect encodingId!
147+ if ( record . platformId == 3 )
148+ {
149+ return GetWindowsEncoding ( record . encodingId ) ;
131150 }
132151
133- // Fallback – borde aldrig hända
152+ // Fallback for unknown platforms
134153 return Encoding . UTF8 ;
135154 }
136155
156+ // ADD GetWindowsEncoding() method:
157+ private static Encoding GetWindowsEncoding ( ushort encodingId )
158+ {
159+ try
160+ {
161+ switch ( encodingId )
162+ {
163+ case 0 :
164+ // Symbol encoding – fallback to Windows-1252
165+ return Encoding . GetEncoding ( 1252 ) ;
166+
167+ case 1 :
168+ // Unicode BMP (UCS-2) – UTF-16BE
169+ // THIS IS THE MOST COMMON for modern fonts!
170+ return Encoding . BigEndianUnicode ;
171+
172+ case 2 :
173+ // Shift-JIS – Japanese
174+ return Encoding . GetEncoding ( 932 ) ;
175+
176+ case 3 :
177+ // GB2312 – Simplified Chinese
178+ return Encoding . GetEncoding ( 936 ) ;
179+
180+ case 4 :
181+ // Big5 – Traditional Chinese
182+ return Encoding . GetEncoding ( 950 ) ;
183+
184+ case 5 :
185+ // Wansung – Korean
186+ return Encoding . GetEncoding ( 949 ) ;
187+
188+ case 6 :
189+ // Johab – Korean (alternative)
190+ return Encoding . GetEncoding ( 1361 ) ;
191+
192+ case 10 :
193+ // Unicode full repertoire
194+ // .NET doesn't have UTF-32BE directly, use UTF-16BE
195+ return Encoding . BigEndianUnicode ;
196+
197+ default :
198+ // Fallback for unknown encodings
199+ return Encoding . BigEndianUnicode ;
200+ }
201+ }
202+ catch ( NotSupportedException )
203+ {
204+ // If encoding doesn't exist (e.g. in .NET Standard without System.Text.Encoding.CodePages)
205+ // Fallback to UTF-16BE - this is safe for most modern fonts
206+ return Encoding . BigEndianUnicode ;
207+ }
208+ catch ( ArgumentException )
209+ {
210+ return Encoding . BigEndianUnicode ;
211+ }
212+ }
213+
137214 //private Encoding GetEncodingForRecord(NameRecord record)
138215 //{
139216 // if (record.platformId == 0)
0 commit comments