@@ -18,6 +18,7 @@ Date Author Change
1818using EPPlus . Fonts . OpenType . Tables . Gpos . Data . Lookups . LookupType4 ;
1919using System ;
2020using System . Collections . Generic ;
21+ using System . Diagnostics ;
2122
2223namespace EPPlus . Fonts . OpenType . Tables . Gpos
2324{
@@ -114,7 +115,6 @@ private LookupListTable ReadLookupList(FontsBinaryReader reader, long lookupList
114115 private LookupTable ReadLookup ( FontsBinaryReader reader , long lookupStart )
115116 {
116117 var lookup = new LookupTable ( ) ;
117-
118118 lookup . LookupType = reader . ReadUInt16BigEndian ( ) ;
119119 lookup . LookupFlag = reader . ReadUInt16BigEndian ( ) ;
120120 ushort subTableCount = reader . ReadUInt16BigEndian ( ) ;
@@ -132,14 +132,15 @@ private LookupTable ReadLookup(FontsBinaryReader reader, long lookupStart)
132132 }
133133
134134 lookup . SubTables = new List < FontTableElement > ( ) ;
135-
136135 for ( int i = 0 ; i < subTableCount ; i ++ )
137136 {
138137 if ( subTableOffsets [ i ] == 0 )
138+ {
139139 continue ;
140+ }
140141
141142 reader . BaseStream . Position = lookupStart + subTableOffsets [ i ] ;
142- var subTable = ReadSubTable ( reader , lookup . LookupType , lookupStart + subTableOffsets [ i ] ) ;
143+ var subTable = ReadSubTable ( reader , lookup . LookupType , lookupStart + subTableOffsets [ i ] ) ;
143144
144145 if ( subTable != null )
145146 {
@@ -194,7 +195,7 @@ private FontTableElement ReadSubTable(FontsBinaryReader reader, ushort lookupTyp
194195 case 9 :
195196 // Extension positioning
196197 // TODO: Implement when needed
197- return null ;
198+ return ReadExtensionPosSubTable ( reader , subtableStart ) ;
198199
199200 default :
200201 // Unknown lookup type - skip
@@ -204,14 +205,19 @@ private FontTableElement ReadSubTable(FontsBinaryReader reader, ushort lookupTyp
204205
205206 private FontTableElement ReadPairPosSubTable ( FontsBinaryReader reader , long subtableStart )
206207 {
208+ // ✅ FIX: Sätt position först!
209+ reader . BaseStream . Position = subtableStart ;
210+
207211 ushort posFormat = reader . ReadUInt16BigEndian ( ) ;
208212
209213 if ( posFormat == 1 )
210214 {
215+ reader . BaseStream . Position = subtableStart ; // Reset för deserializer
211216 return ReadPairPosFormat1 ( reader , subtableStart ) ;
212217 }
213218 else if ( posFormat == 2 )
214219 {
220+ reader . BaseStream . Position = subtableStart ; // Reset för deserializer
215221 return ReadPairPosFormat2 ( reader , subtableStart ) ;
216222 }
217223 else
@@ -236,10 +242,14 @@ private PairPosSubTableFormat2 ReadPairPosFormat2(FontsBinaryReader reader, long
236242
237243 private FontTableElement ReadSinglePosSubTable ( FontsBinaryReader reader , long subtableStart )
238244 {
245+ // ✅ FIX: Sätt position FÖRST
246+ reader . BaseStream . Position = subtableStart ;
247+
239248 // Read format to determine which deserializer to use
240- long savedPos = reader . BaseStream . Position ;
241249 ushort posFormat = reader . ReadUInt16BigEndian ( ) ;
242- reader . BaseStream . Position = savedPos ; // Reset for deserializer
250+
251+ // Reset for deserializer
252+ reader . BaseStream . Position = subtableStart ;
243253
244254 if ( posFormat == 1 )
245255 {
@@ -259,21 +269,52 @@ private FontTableElement ReadSinglePosSubTable(FontsBinaryReader reader, long su
259269
260270 private FontTableElement ReadMarkToBaseSubTable ( FontsBinaryReader reader , long subtableStart )
261271 {
262- // Read format to verify it's Format 1 (only format for MarkToBase)
263- long savedPos = reader . BaseStream . Position ;
272+ // ✅ FIX: Sätt position INNAN du läser format
273+ reader . BaseStream . Position = subtableStart ;
274+
264275 ushort posFormat = reader . ReadUInt16BigEndian ( ) ;
265- reader . BaseStream . Position = savedPos ; // Reset for deserializer
276+
277+ // Reset to start for deserializer
278+ reader . BaseStream . Position = subtableStart ;
266279
267280 if ( posFormat == 1 )
268281 {
269282 var deserializer = new MarkToBaseSubTableFormat1Deserializer ( reader ) ;
270- return deserializer . Deserialize ( subtableStart ) ;
283+ var result = deserializer . Deserialize ( subtableStart ) ;
284+ return result ;
271285 }
272286 else
273287 {
274- // Unknown format - skip silently
275288 return null ;
276289 }
277290 }
291+
292+ private FontTableElement ReadExtensionPosSubTable ( FontsBinaryReader reader , long subtableStart )
293+ {
294+ reader . BaseStream . Position = subtableStart ;
295+
296+ ushort posFormat = reader . ReadUInt16BigEndian ( ) ;
297+
298+ if ( posFormat != 1 )
299+ {
300+ return null ;
301+ }
302+
303+ ushort extensionLookupType = reader . ReadUInt16BigEndian ( ) ;
304+ uint extensionOffset = reader . ReadUInt32BigEndian ( ) ;
305+
306+
307+ // ✅ CRITICAL: Prevent infinite recursion!
308+ if ( extensionLookupType == 9 )
309+ {
310+ return null ;
311+ }
312+
313+ long wrappedSubtableStart = subtableStart + extensionOffset ;
314+
315+ var result = ReadSubTable ( reader , extensionLookupType , wrappedSubtableStart ) ;
316+
317+ return result ;
318+ }
278319 }
279320}
0 commit comments