GlyphSubstitutionClass.cs 109 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Runtime.InteropServices;
  5. using FastReport.Fonts.LinqExts;
  6. #pragma warning disable CS3001, CS3002, CS3003, CS1591 // Missing XML comment for publicly visible type or member
  7. namespace FastReport.Fonts
  8. {
  9. /// <summary>
  10. /// GlyphSubstitution table
  11. /// </summary>
  12. public class GlyphSubstitutionClass : TrueTypeTable
  13. {
  14. #region "Structure definition"
  15. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  16. public struct GSUB_Header
  17. {
  18. [FieldOffset(0)]
  19. public uint Version; // Version of the GSUB table-initially set to 0x00010000
  20. [FieldOffset(4)]
  21. public ushort ScriptList; // Offset to ScriptList table-from beginning of GSUB table
  22. [FieldOffset(6)]
  23. public ushort FeatureList; // Offset to FeatureList table-from beginning of GSUB table
  24. [FieldOffset(8)]
  25. public ushort LookupList; // Offset to LookupList table-from beginning of GSUB table
  26. }
  27. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  28. public struct ScriptListTable
  29. {
  30. [FieldOffset(0)]
  31. public ushort CountScripts; // Count of ScriptListRecord
  32. }
  33. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  34. public struct ScriptListRecord
  35. {
  36. [FieldOffset(0)]
  37. public uint ScriptTag; // 4-byte ScriptTag identifier
  38. [FieldOffset(4)]
  39. public ushort ScriptOffset; // Offset to Script table-from beginning of ScriptList
  40. }
  41. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  42. public struct ScriptTable
  43. {
  44. [FieldOffset(0)]
  45. public ushort DefaultLangSys; // Offset to DefaultLangSys table-from beginning of Script table-may be NULL
  46. [FieldOffset(2)]
  47. public ushort LangSysCount; // Number of LangSysRecords for this script-excluding the DefaultLangSys
  48. }
  49. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  50. public struct LangSysRecord
  51. {
  52. [FieldOffset(0)]
  53. public uint LangSysTag; // 4-byte LangSysTag identifier
  54. [FieldOffset(4)]
  55. public ushort LangSys; // Offset to LangSys table-from beginning of Script table
  56. }
  57. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  58. public struct LangSysTable
  59. {
  60. [FieldOffset(0)]
  61. public ushort LookupOrder; // = NULL (reserved for an offset to a reordering table)
  62. [FieldOffset(2)]
  63. public ushort ReqFeatureIndex; // Index of a feature required for this language system- if no required features = 0xFFFF
  64. [FieldOffset(4)]
  65. public ushort FeatureCount; // Number of FeatureIndex values for this language system-excludes the required feature
  66. }
  67. // Related to feature table
  68. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  69. public struct FeaturesListTable
  70. {
  71. [FieldOffset(0)]
  72. public ushort CountFeatures; // Count of FeaturesListRecord
  73. }
  74. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  75. public struct FeatureRecord
  76. {
  77. [FieldOffset(0)]
  78. public uint FeatureTag; // 4-byte feature identification tag
  79. [FieldOffset(4)]
  80. public ushort Feature; // Offset to Feature table-from beginning of FeatureList
  81. }
  82. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  83. public struct FeatureTable
  84. {
  85. [FieldOffset(0)]
  86. public ushort FeatureParams;
  87. [FieldOffset(2)]
  88. public ushort LookupCount;
  89. }
  90. #endregion
  91. private GSUB_Header header;
  92. private IntPtr gsub_ptr;
  93. private Hashtable script_list = new Hashtable();
  94. private LookupEntry[] lookup_list;
  95. public IEnumerable<string> Scripts
  96. {
  97. get
  98. {
  99. foreach (string script_str in script_list.Keys)
  100. yield return script_str;
  101. }
  102. }
  103. private ushort[] LoadFeature(uint feature_idx, out string FeatureTag)
  104. {
  105. IntPtr feature_list_table_ptr = Increment(gsub_ptr, (int)header.FeatureList);
  106. ushort feature_count = SwapUInt16((ushort)Marshal.PtrToStructure(feature_list_table_ptr, typeof(ushort)));
  107. if (feature_idx >= feature_count) throw new Exception("Feature index out of bound");
  108. IntPtr feature_record_ptr = Increment(feature_list_table_ptr, (int)(sizeof(ushort) + feature_idx * 6));
  109. FeatureRecord feature_record = (FeatureRecord)Marshal.PtrToStructure(feature_record_ptr, typeof(FeatureRecord));
  110. feature_record.Feature = SwapUInt16(feature_record.Feature);
  111. FeatureTag = "" +
  112. (char)(0xff & feature_record.FeatureTag) +
  113. (char)(0xff & (feature_record.FeatureTag >> 8)) +
  114. (char)(0xff & (feature_record.FeatureTag >> 16)) +
  115. (char)(0xff & (feature_record.FeatureTag >> 24));
  116. IntPtr feature_table_ptr = Increment(feature_list_table_ptr, feature_record.Feature);
  117. FeatureTable feature_table = (FeatureTable)Marshal.PtrToStructure(feature_table_ptr, typeof(FeatureTable));
  118. feature_table.LookupCount = SwapUInt16(feature_table.LookupCount);
  119. ushort[] OffsetLookupList = new ushort[feature_table.LookupCount];
  120. IntPtr lookup_list_ptr = Increment(feature_table_ptr, Marshal.SizeOf(feature_table));
  121. for (int i = 0; i < feature_table.LookupCount; i++)
  122. {
  123. ushort lookuip_index = SwapUInt16((ushort)Marshal.PtrToStructure(lookup_list_ptr, typeof(ushort)));
  124. OffsetLookupList[i] = lookuip_index;
  125. if (lookuip_index == 30)
  126. {
  127. //to do remove
  128. }
  129. lookup_list_ptr = Increment(lookup_list_ptr, sizeof(ushort));
  130. }
  131. return OffsetLookupList;
  132. }
  133. internal IEnumerable<string> GetFeatures(string script, string language)
  134. {
  135. if (script_list.ContainsKey(script))
  136. if ((script_list[script] as Hashtable).ContainsKey(language))
  137. {
  138. foreach (string feature_str in ((script_list[script] as Hashtable)[language] as Hashtable).Keys)
  139. yield return feature_str;
  140. }
  141. }
  142. internal IEnumerable<string> Languages(string script)
  143. {
  144. if (script_list.ContainsKey(script))
  145. {
  146. foreach (string lang_str in (script_list[script] as Hashtable).Keys)
  147. yield return lang_str;
  148. }
  149. }
  150. private Hashtable LoadLanguageSystemTable(IntPtr lang_sys_rec_ptr)
  151. {
  152. Hashtable Features = new Hashtable();
  153. LangSysTable lang_sys_table = (LangSysTable)Marshal.PtrToStructure(lang_sys_rec_ptr, typeof(LangSysTable));
  154. lang_sys_table.LookupOrder = SwapUInt16(lang_sys_table.LookupOrder);
  155. lang_sys_table.ReqFeatureIndex = SwapUInt16(lang_sys_table.ReqFeatureIndex);
  156. lang_sys_table.FeatureCount = SwapUInt16(lang_sys_table.FeatureCount);
  157. IntPtr feature_index_ptr = Increment(lang_sys_rec_ptr, Marshal.SizeOf(lang_sys_table));
  158. ushort[] feature_indexes = new ushort[lang_sys_table.FeatureCount];
  159. for (int k = 0; k < lang_sys_table.FeatureCount; k++)
  160. {
  161. feature_indexes[k] = SwapUInt16((ushort)Marshal.PtrToStructure(feature_index_ptr, typeof(ushort)));
  162. string FeatureTag;
  163. ushort[] LookupOffsets = LoadFeature(feature_indexes[k], out FeatureTag);
  164. #if DEBUG_TTF
  165. Console.WriteLine("\t\t[" + k + "]: " + FeatureTag + " of " + LookupOffsets.Length);
  166. #endif
  167. if (!Features.ContainsKey(FeatureTag))
  168. Features.Add(FeatureTag, LookupOffsets);
  169. #if DEBUG_TTF
  170. else
  171. Console.WriteLine("Duplicated record " + FeatureTag);
  172. #endif
  173. feature_index_ptr = Increment(feature_index_ptr, sizeof(ushort));
  174. }
  175. return Features;
  176. }
  177. private void LoadScriptList()
  178. {
  179. IntPtr script_list_table_ptr = Increment(gsub_ptr, (int)header.ScriptList);
  180. ScriptListTable script_list_table = (ScriptListTable)Marshal.PtrToStructure(script_list_table_ptr, typeof(ScriptListTable));
  181. script_list_table.CountScripts = SwapUInt16(script_list_table.CountScripts);
  182. IntPtr script_record_ptr = Increment(script_list_table_ptr, Marshal.SizeOf(script_list_table));
  183. for (int i = 0; i < script_list_table.CountScripts; i++)
  184. {
  185. ScriptListRecord script_record = (ScriptListRecord)Marshal.PtrToStructure(script_record_ptr, typeof(ScriptListRecord));
  186. script_record.ScriptOffset = SwapUInt16(script_record.ScriptOffset);
  187. string ScriptTag = "" +
  188. (char)(0xff & script_record.ScriptTag) +
  189. (char)(0xff & (script_record.ScriptTag >> 8)) +
  190. (char)(0xff & (script_record.ScriptTag >> 16)) +
  191. (char)(0xff & (script_record.ScriptTag >> 24));
  192. #if DEBUG_TTF
  193. Console.WriteLine("[" + ScriptTag + "]");
  194. #endif
  195. Hashtable lang_sys_hash = new Hashtable();
  196. script_list.Add(ScriptTag, lang_sys_hash);
  197. IntPtr script_table_ptr = Increment(script_list_table_ptr, script_record.ScriptOffset);
  198. ScriptTable script_table = (ScriptTable)Marshal.PtrToStructure(script_table_ptr, typeof(ScriptTable));
  199. script_table.DefaultLangSys = SwapUInt16(script_table.DefaultLangSys);
  200. script_table.LangSysCount = SwapUInt16(script_table.LangSysCount);
  201. IntPtr lang_sys_rec_ptr;
  202. if (script_table.DefaultLangSys != 0)
  203. {
  204. lang_sys_rec_ptr = Increment(script_table_ptr, script_table.DefaultLangSys);
  205. #if DEBUG_TTF
  206. Console.WriteLine("\t\"!DEF\"");
  207. #endif
  208. lang_sys_hash.Add("", LoadLanguageSystemTable(lang_sys_rec_ptr));
  209. }
  210. lang_sys_rec_ptr = Increment(script_table_ptr, Marshal.SizeOf(script_table));
  211. for (int j = 0; j < script_table.LangSysCount; j++)
  212. {
  213. LangSysRecord lang_sys_rec = (LangSysRecord)Marshal.PtrToStructure(lang_sys_rec_ptr, typeof(LangSysRecord));
  214. lang_sys_rec.LangSys = SwapUInt16(lang_sys_rec.LangSys);
  215. string LangSysTag = "" +
  216. (char)(0xff & lang_sys_rec.LangSysTag) +
  217. (char)(0xff & (lang_sys_rec.LangSysTag >> 8)) +
  218. (char)(0xff & (lang_sys_rec.LangSysTag >> 16)) +
  219. (char)(0xff & (lang_sys_rec.LangSysTag >> 24));
  220. #if DEBUG_TTF
  221. Console.WriteLine("\t\"" + LangSysTag + "\"");
  222. #endif
  223. IntPtr lang_sys_rec_ptr_offset = Increment(script_table_ptr, lang_sys_rec.LangSys);
  224. lang_sys_hash.Add(LangSysTag, LoadLanguageSystemTable(lang_sys_rec_ptr_offset));
  225. lang_sys_rec_ptr = Increment(lang_sys_rec_ptr, Marshal.SizeOf(lang_sys_rec));
  226. }
  227. script_record_ptr = Increment(script_record_ptr, Marshal.SizeOf(script_record));
  228. }
  229. }
  230. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  231. internal struct LookupTableRecordHeader
  232. {
  233. [FieldOffset(0)]
  234. public ushort LookupType; // Different enumerations for GSUB and GPOS
  235. [FieldOffset(2)]
  236. public ushort LookupFlag; // Lookup qualifiers
  237. [FieldOffset(4)]
  238. public ushort SubTableCount; // Number of SubTables for this lookup [FieldOffset(2)]
  239. }
  240. internal struct LookupEntry
  241. {
  242. public LookupTableRecordHeader record_header;
  243. public ushort[] subtable_offsets;
  244. public IntPtr[] subtable_ptrs;
  245. public Substitution[] subs;
  246. public override string ToString()
  247. {
  248. return "" + ((LookupTypes)record_header.LookupType).ToString() + " : " + record_header.LookupFlag + " [" + record_header.SubTableCount.ToString() + "]";
  249. }
  250. }
  251. public enum LookupTypes
  252. {
  253. Single = 1, // Replace one glyph with one glyph
  254. Multiple = 2, // Replace one glyph with more than one glyph
  255. Alternate = 3, // Replace one glyph with one of many glyphs
  256. Ligature = 4, // Replace multiple glyphs with one glyph
  257. Context = 5, // Replace one or more glyphs in context
  258. ChainingContext = 6, // Replace one or more glyphs in chained context
  259. ExtensionSubstitution = 7, // Extension mechanism for other substitutions (i.e. this excludes the Extension type substitution itself)
  260. ReverseChainingContextSingle = 8 // Applied in reverse order, replace single glyph in chaining context
  261. //9+ Reserved For future use (set to zero)
  262. }
  263. private void LoadLookupList()
  264. {
  265. IntPtr lookup_list_table_ptr = Increment(gsub_ptr, (int)header.LookupList);
  266. ushort LookupListCount = SwapUInt16((ushort)Marshal.PtrToStructure(lookup_list_table_ptr, typeof(ushort)));
  267. lookup_list = new LookupEntry[LookupListCount];
  268. IntPtr lookup_list_ptr = Increment(lookup_list_table_ptr, sizeof(ushort));
  269. for (int i = 0; i < LookupListCount; i++)
  270. {
  271. ushort lookup_index = SwapUInt16((ushort)Marshal.PtrToStructure(lookup_list_ptr, typeof(ushort)));
  272. lookup_list_ptr = Increment(lookup_list_ptr, sizeof(ushort));
  273. IntPtr lookup_list_entry_ptr = Increment(lookup_list_table_ptr, lookup_index);
  274. IntPtr lookup_table_ptr = lookup_list_entry_ptr;
  275. lookup_list[i].record_header = (LookupTableRecordHeader)Marshal.PtrToStructure(lookup_list_entry_ptr, typeof(LookupTableRecordHeader));
  276. lookup_list_entry_ptr = Increment(lookup_list_entry_ptr, Marshal.SizeOf(lookup_list[i].record_header));
  277. lookup_list[i].record_header.LookupType = SwapUInt16(lookup_list[i].record_header.LookupType);
  278. lookup_list[i].record_header.LookupFlag = SwapUInt16(lookup_list[i].record_header.LookupFlag);
  279. lookup_list[i].record_header.SubTableCount = SwapUInt16(lookup_list[i].record_header.SubTableCount);
  280. lookup_list[i].subtable_offsets = new ushort[lookup_list[i].record_header.SubTableCount];
  281. lookup_list[i].subtable_ptrs = new IntPtr[lookup_list[i].record_header.SubTableCount];
  282. lookup_list[i].subs = new Substitution[lookup_list[i].record_header.SubTableCount];
  283. for (int j = 0; j < lookup_list[i].record_header.SubTableCount; j++)
  284. {
  285. lookup_list[i].subtable_offsets[j] = SwapUInt16((ushort)Marshal.PtrToStructure(lookup_list_entry_ptr, typeof(ushort)));
  286. lookup_list[i].subtable_ptrs[j] = Increment(lookup_table_ptr, lookup_list[i].subtable_offsets[j]);
  287. lookup_list_entry_ptr = Increment(lookup_list_entry_ptr, sizeof(ushort));
  288. lookup_list[i].subs[j] = LoadSubstitution(lookup_list[i].record_header.LookupType, lookup_list[i].subtable_ptrs[j]);
  289. }
  290. //to do: lookup list
  291. }
  292. }
  293. private Substitution LoadSubstitution(ushort lookupType, IntPtr intPtr)
  294. {
  295. #if DEBUG_TTF
  296. Console.WriteLine("\tLookupType[" + ((LookupTypes)lookupType).ToString() + "]");
  297. #endif
  298. switch ((LookupTypes)lookupType)
  299. {
  300. case LookupTypes.Single:
  301. return LoadSingleSubstitution(intPtr);
  302. case LookupTypes.Multiple:
  303. return LoadMultipleSubstitution(intPtr);
  304. case LookupTypes.Alternate:
  305. break;
  306. case LookupTypes.Ligature:
  307. return LoadLigaturesSubtable(intPtr);
  308. //break;
  309. case LookupTypes.Context:
  310. return LoadContextSubstitution(intPtr);
  311. //break;
  312. case LookupTypes.ChainingContext:
  313. return LoadChainingContext(intPtr);
  314. //break;
  315. case LookupTypes.ExtensionSubstitution:
  316. ExtensionSubstFormat extensionSubstFormat = (ExtensionSubstFormat)
  317. Marshal.PtrToStructure(intPtr,
  318. typeof(ExtensionSubstFormat));
  319. extensionSubstFormat.ExtensionLookupType = SwapUInt16(extensionSubstFormat.ExtensionLookupType);
  320. extensionSubstFormat.SubstFormat = SwapUInt16(extensionSubstFormat.SubstFormat);
  321. extensionSubstFormat.ExtensionOffset = SwapUInt32(extensionSubstFormat.ExtensionOffset);
  322. Extension extension = new Extension();
  323. extension.Format = extensionSubstFormat.SubstFormat;
  324. extension.LookupType = extensionSubstFormat.ExtensionLookupType;
  325. extension.Substitution = LoadSubstitution(
  326. extension.LookupType,
  327. Increment(intPtr, extensionSubstFormat.ExtensionOffset));
  328. return extension;
  329. case LookupTypes.ReverseChainingContextSingle:
  330. break;
  331. }
  332. return new VoidSubstitution();
  333. }
  334. private Substitution LoadContextSubstitution(IntPtr lookup_entry)
  335. {
  336. ushort format = (ushort)Marshal.PtrToStructure(lookup_entry, typeof(ushort));
  337. format = SwapUInt16(format);
  338. switch (format)
  339. {
  340. case 1:
  341. ContextSubstFormat1 type1 = (ContextSubstFormat1)Marshal.PtrToStructure(lookup_entry, typeof(ContextSubstFormat1));
  342. type1.SubstFormat = SwapUInt16(type1.SubstFormat);
  343. type1.Coverage = SwapUInt16(type1.Coverage);
  344. type1.SubRuleSetCount = SwapUInt16(type1.SubRuleSetCount);
  345. IntPtr sets_offset = Increment(lookup_entry, Marshal.SizeOf(type1));
  346. Contextual1.SubRule[][] subRuleSets = new Contextual1.SubRule[type1.SubRuleSetCount][];
  347. for (int i = 0; i < type1.SubRuleSetCount; i++)
  348. {
  349. ushort offset = (ushort)Marshal.PtrToStructure(sets_offset, typeof(ushort));
  350. offset = SwapUInt16(offset);
  351. IntPtr subruleset_offset_table = Increment(lookup_entry, offset);
  352. ushort subRuleCount = (ushort)Marshal.PtrToStructure(subruleset_offset_table, typeof(ushort));
  353. subRuleCount = SwapUInt16(subRuleCount);
  354. IntPtr subrule_offsets = Increment(subruleset_offset_table, Marshal.SizeOf(subRuleCount));
  355. Contextual1.SubRule[] subRuleSet = new Contextual1.SubRule[subRuleCount];
  356. for (int j = 0; j < subRuleCount; j++)
  357. {
  358. ushort subRuleOffset = (ushort)Marshal.PtrToStructure(subrule_offsets, typeof(ushort));
  359. IntPtr subrule_table = Increment(subruleset_offset_table, subRuleOffset);
  360. SubRuleTable subRule = (SubRuleTable)Marshal.PtrToStructure(subrule_table, typeof(SubRuleTable));
  361. IntPtr subrule_table_arrays = Increment(subrule_table, Marshal.SizeOf(subRule));
  362. subRule.GlyphCount = SwapUInt16(subRule.GlyphCount);
  363. subRule.SubstitutionCount = SwapUInt16(subRule.SubstitutionCount);
  364. ushort[] glyphs = new ushort[subRule.GlyphCount - 1];
  365. for (int k = 0; k < subRule.GlyphCount - 1; k++)
  366. {
  367. ushort glyph = (ushort)Marshal.PtrToStructure(subrule_table_arrays, typeof(ushort));
  368. glyph = SwapUInt16(glyph);
  369. subrule_table_arrays = Increment(subrule_table_arrays, Marshal.SizeOf(glyph));
  370. glyphs[k] = glyph;
  371. }
  372. SubstLookupRecord[] records = new SubstLookupRecord[subRule.SubstitutionCount];
  373. for (int k = 0; k < subRule.SubstitutionCount; k++)
  374. {
  375. SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(subrule_table_arrays, typeof(SubstLookupRecord));
  376. record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
  377. record.LookupListIndex = SwapUInt16(record.LookupListIndex);
  378. subrule_table_arrays = Increment(subrule_table_arrays, Marshal.SizeOf(record));
  379. records[k] = record;
  380. }
  381. subRuleSet[j] = new Contextual1.SubRule(glyphs, records);
  382. subrule_offsets = Increment(subrule_offsets, Marshal.SizeOf(subRuleOffset));
  383. }
  384. subRuleSets[i] = subRuleSet;
  385. sets_offset = Increment(lookup_entry, Marshal.SizeOf(offset));
  386. }
  387. return new Contextual1(this, subRuleSets, LoadCoverage(Increment(lookup_entry, type1.Coverage)));
  388. case 2:
  389. ContextSubstFormat2 type2 = (ContextSubstFormat2)Marshal.PtrToStructure(lookup_entry, typeof(ContextSubstFormat2));
  390. type2.SubstFormat = SwapUInt16(type2.SubstFormat);
  391. type2.Coverage = SwapUInt16(type2.Coverage);
  392. type2.ClassDefOffset = SwapUInt16(type2.ClassDefOffset);
  393. type2.SubClassSetCount = SwapUInt16(type2.SubClassSetCount);
  394. Contextual2.SubClassRule[][] subClassRuleSets = new Contextual2.SubClassRule[type2.SubClassSetCount][];
  395. IntPtr sub_class_set_offset = Increment(lookup_entry, Marshal.SizeOf(type2));
  396. for (int i = 0; i < type2.SubClassSetCount; i++)
  397. {
  398. ushort offset = (ushort)Marshal.PtrToStructure(sub_class_set_offset, typeof(ushort));
  399. if (offset == 0)
  400. subClassRuleSets[i] = null;
  401. else
  402. {
  403. offset = SwapUInt16(offset);
  404. IntPtr sub_class_set_table = Increment(lookup_entry, offset);
  405. ushort count = (ushort)Marshal.PtrToStructure(sub_class_set_table, typeof(ushort));
  406. count = SwapUInt16(count);
  407. IntPtr sub_class_rule_offset = Increment(sub_class_set_table, Marshal.SizeOf(count));
  408. Contextual2.SubClassRule[] subClassSet = new Contextual2.SubClassRule[count];
  409. for (int j = 0; j < count; j++)
  410. {
  411. ushort offset2 = (ushort)Marshal.PtrToStructure(sub_class_rule_offset, typeof(ushort));
  412. offset2 = SwapUInt16(offset2);
  413. IntPtr sub_class_rule_table = Increment(sub_class_set_table, offset2);
  414. SubClassRule subClassRule = (SubClassRule)Marshal.PtrToStructure(sub_class_rule_table, typeof(SubClassRule));
  415. IntPtr subclassrule_table_arrays = Increment(sub_class_rule_table, Marshal.SizeOf(subClassRule));
  416. subClassRule.ClassCount = SwapUInt16(subClassRule.ClassCount);
  417. subClassRule.SubstitutionCount = SwapUInt16(subClassRule.SubstitutionCount);
  418. ushort[] glyphClassess = new ushort[subClassRule.ClassCount - 1];
  419. for (int k = 0; k < subClassRule.ClassCount - 1; k++)
  420. {
  421. ushort glyphClass = (ushort)Marshal.PtrToStructure(subclassrule_table_arrays, typeof(ushort));
  422. glyphClass = SwapUInt16(glyphClass);
  423. subclassrule_table_arrays = Increment(subclassrule_table_arrays, Marshal.SizeOf(glyphClass));
  424. glyphClassess[k] = glyphClass;
  425. }
  426. SubstLookupRecord[] records = new SubstLookupRecord[subClassRule.SubstitutionCount];
  427. for (int k = 0; k < subClassRule.SubstitutionCount; k++)
  428. {
  429. SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(subclassrule_table_arrays, typeof(SubstLookupRecord));
  430. record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
  431. record.LookupListIndex = SwapUInt16(record.LookupListIndex);
  432. subclassrule_table_arrays = Increment(subclassrule_table_arrays, Marshal.SizeOf(record));
  433. records[k] = record;
  434. }
  435. subClassSet[j] = new Contextual2.SubClassRule(glyphClassess, records);
  436. sub_class_rule_offset = Increment(sub_class_rule_offset, Marshal.SizeOf(offset2));
  437. }
  438. subClassRuleSets[i] = subClassSet;
  439. }
  440. sub_class_set_offset = Increment(sub_class_set_offset, Marshal.SizeOf(offset));
  441. }
  442. return new Contextual2(this, subClassRuleSets, LoadCoverage(Increment(lookup_entry, type2.Coverage)), LoadClassDefinition(Increment(lookup_entry, type2.ClassDefOffset)));
  443. case 3:
  444. ContextSubstFormat3 type3 = (ContextSubstFormat3)Marshal.PtrToStructure(lookup_entry, typeof(ContextSubstFormat3));
  445. type3.SubstFormat = SwapUInt16(type3.SubstFormat);
  446. type3.GlyphCount = SwapUInt16(type3.GlyphCount);
  447. type3.SubstitutionCount = SwapUInt16(type3.SubstitutionCount);
  448. Coverage[] coverages = new Coverage[type3.GlyphCount];
  449. SubstLookupRecord[] subRecords = new SubstLookupRecord[type3.SubstitutionCount];
  450. IntPtr type3_arrays = Increment(lookup_entry, Marshal.SizeOf(type3));
  451. for (int i = 0; i < type3.GlyphCount; i++)
  452. {
  453. ushort offset = (ushort)Marshal.PtrToStructure(type3_arrays, typeof(ushort));
  454. offset = SwapUInt16(offset);
  455. coverages[i] = LoadCoverage(Increment(lookup_entry, offset));
  456. type3_arrays = Increment(type3_arrays, Marshal.SizeOf(offset));
  457. }
  458. for (int i = 0; i < type3.SubstitutionCount; i++)
  459. {
  460. SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(type3_arrays, typeof(SubstLookupRecord));
  461. record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
  462. record.LookupListIndex = SwapUInt16(record.LookupListIndex);
  463. subRecords[i] = record;
  464. type3_arrays = Increment(type3_arrays, Marshal.SizeOf(record));
  465. }
  466. return new Contextual3(this, subRecords, coverages);
  467. }
  468. return new VoidSubstitution();
  469. }
  470. private Substitution LoadMultipleSubstitution(IntPtr lookup_entry)
  471. {
  472. MultipleSubstFormat1 type1 = (MultipleSubstFormat1)Marshal.PtrToStructure(lookup_entry, typeof(MultipleSubstFormat1));
  473. type1.SubstFormat = SwapUInt16(type1.SubstFormat);
  474. type1.Coverage = SwapUInt16(type1.Coverage);
  475. type1.SequenceCount = SwapUInt16(type1.SequenceCount);
  476. //type1.SequenceOffset = SwapUInt16(type1.SequenceOffset);
  477. IntPtr sequence_offset = Increment(lookup_entry, Marshal.SizeOf(type1));
  478. ushort[][] sequences = new ushort[type1.SequenceCount][];
  479. for (int i = 0; i < type1.SequenceCount; i++)
  480. {
  481. ushort offset = (ushort)Marshal.PtrToStructure(sequence_offset, typeof(ushort));
  482. offset = SwapUInt16(offset);
  483. IntPtr sequence_offset_table = Increment(lookup_entry, offset);
  484. ushort glyph_count = (ushort)Marshal.PtrToStructure(sequence_offset_table, typeof(ushort));
  485. glyph_count = SwapUInt16(glyph_count);
  486. ushort[] glyphs = new ushort[glyph_count];
  487. for (int j = 0; j < glyph_count; j++)
  488. {
  489. glyphs[j] = (ushort)Marshal.PtrToStructure(sequence_offset_table, typeof(ushort));
  490. glyphs[j] = SwapUInt16(glyphs[j]);
  491. sequence_offset_table = Increment(lookup_entry, Marshal.SizeOf(glyphs[j]));
  492. }
  493. sequences[i] = glyphs;
  494. sequence_offset = Increment(lookup_entry, Marshal.SizeOf(offset));
  495. }
  496. return new Multiple(sequences, LoadCoverage(Increment(lookup_entry, type1.Coverage)));
  497. //return new VoidSubstitution();
  498. }
  499. private Substitution LoadSingleSubstitution(IntPtr lookup_entry)
  500. {
  501. SignleSubstitutionFormat1 type1 = (SignleSubstitutionFormat1)Marshal.PtrToStructure(lookup_entry, typeof(SignleSubstitutionFormat1));
  502. type1.SubstFormat = SwapUInt16(type1.SubstFormat);
  503. type1.Coverage = SwapUInt16(type1.Coverage);
  504. type1.DeltaGlyphID = SwapInt16(type1.DeltaGlyphID);
  505. switch (type1.SubstFormat)
  506. {
  507. case 1:
  508. return new Single1(type1.DeltaGlyphID, LoadCoverage(Increment(lookup_entry, type1.Coverage)));
  509. case 2:
  510. ushort[] substitute = new ushort[type1.DeltaGlyphID];
  511. IntPtr lookup_entry_substitute = Increment(lookup_entry, Marshal.SizeOf(typeof(SignleSubstitutionFormat1)));
  512. for (int i = 0; i < type1.DeltaGlyphID; i++)
  513. {
  514. substitute[i] = (ushort)Marshal.PtrToStructure(lookup_entry_substitute, typeof(ushort));
  515. substitute[i] = SwapUInt16(substitute[i]);
  516. lookup_entry_substitute = Increment(lookup_entry_substitute, Marshal.SizeOf(typeof(ushort)));
  517. }
  518. return new Single2(substitute, LoadCoverage(Increment(lookup_entry, type1.Coverage)));
  519. }
  520. return new VoidSubstitution();
  521. }
  522. private ClassDefinition LoadClassDefinition(IntPtr class_definition_ptr)
  523. {
  524. ushort class_format = (ushort)Marshal.PtrToStructure(class_definition_ptr, typeof(ushort));
  525. class_format = SwapUInt16(class_format);
  526. switch (class_format)
  527. {
  528. case 1:
  529. ClassDefFormat1 type1 = (ClassDefFormat1)Marshal.PtrToStructure(class_definition_ptr, typeof(ClassDefFormat1));
  530. type1.ClassFormat = SwapUInt16(type1.ClassFormat);
  531. type1.GlyphCount = SwapUInt16(type1.GlyphCount);
  532. type1.StartGlyphID = SwapUInt16(type1.StartGlyphID);
  533. IntPtr class_value_array = Increment(class_definition_ptr, Marshal.SizeOf(type1));
  534. ushort[] classValues = new ushort[type1.GlyphCount];
  535. for (int i = 0; i < type1.GlyphCount; i++)
  536. {
  537. ushort classValue = (ushort)Marshal.PtrToStructure(class_value_array, typeof(ushort));
  538. classValue = SwapUInt16(classValue);
  539. class_value_array = Increment(class_value_array, Marshal.SizeOf(classValue));
  540. }
  541. return new ClassDefinition1(type1.StartGlyphID, classValues);
  542. case 2:
  543. ClassDefFormat2 type2 = (ClassDefFormat2)Marshal.PtrToStructure(class_definition_ptr, typeof(ClassDefFormat2));
  544. type2.ClassFormat = SwapUInt16(type2.ClassFormat);
  545. type2.ClassRangeCount = SwapUInt16(type2.ClassRangeCount);
  546. IntPtr class_records_array = Increment(class_definition_ptr, Marshal.SizeOf(type2));
  547. ClassRangeRecord[] records = new ClassRangeRecord[type2.ClassRangeCount];
  548. for (int i = 0; i < type2.ClassRangeCount; i++)
  549. {
  550. ClassRangeRecord record = (ClassRangeRecord)Marshal.PtrToStructure(class_records_array, typeof(ClassRangeRecord));
  551. record.StartGlyphID = SwapUInt16(record.StartGlyphID);
  552. record.EndGlyphID = SwapUInt16(record.EndGlyphID);
  553. record.ClassValue = SwapUInt16(record.ClassValue);
  554. class_records_array = Increment(class_records_array, Marshal.SizeOf(record));
  555. records[i] = record;
  556. }
  557. return new ClassDefinition2(records);
  558. }
  559. return new VoidClassDefinition();
  560. }
  561. private Coverage LoadCoverage(IntPtr coverage_table_ptr)
  562. {
  563. CoverageHeader ch = (CoverageHeader)Marshal.PtrToStructure(coverage_table_ptr, typeof(CoverageHeader));
  564. ch.CoverageFormat = SwapUInt16(ch.CoverageFormat);
  565. ch.GlyphCount = SwapUInt16(ch.GlyphCount);
  566. switch (ch.CoverageFormat)
  567. {
  568. case 1:
  569. {
  570. ushort[] glyphs = new ushort[ch.GlyphCount];
  571. coverage_table_ptr = Increment(coverage_table_ptr, Marshal.SizeOf(ch));
  572. for (int i = 0; i < ch.GlyphCount; i++)
  573. {
  574. glyphs[i] = SwapUInt16((ushort)Marshal.PtrToStructure(coverage_table_ptr, typeof(ushort)));
  575. coverage_table_ptr = Increment(coverage_table_ptr, Marshal.SizeOf(typeof(ushort)));
  576. }
  577. /*if((new Coverage1(ch.GlyphCount, glyphs)).IsSubstituteGetIndex(296) >=0)
  578. {
  579. //to do remove
  580. }*/
  581. return new Coverage1(ch.GlyphCount, glyphs);
  582. }
  583. //break;
  584. case 2:
  585. {
  586. RangeRecord[] rrs = new RangeRecord[ch.GlyphCount];
  587. coverage_table_ptr = Increment(coverage_table_ptr, Marshal.SizeOf(ch));
  588. for (int i = 0; i < ch.GlyphCount; i++)
  589. {
  590. rrs[i] = (RangeRecord)Marshal.PtrToStructure(coverage_table_ptr, typeof(RangeRecord));
  591. rrs[i].Start = SwapUInt16(rrs[i].Start);
  592. rrs[i].End = SwapUInt16(rrs[i].End);
  593. rrs[i].StartCoverageIndex = SwapUInt16(rrs[i].StartCoverageIndex);
  594. coverage_table_ptr = Increment(coverage_table_ptr, Marshal.SizeOf(rrs[i]));
  595. }
  596. /*if ((new Coverage2(ch.GlyphCount, rrs)).IsSubstituteGetIndex(296) >= 0)
  597. {
  598. //to do remove
  599. }*/
  600. return new Coverage2(ch.GlyphCount, rrs);
  601. }
  602. //break;
  603. }
  604. return new VoidCoverage();
  605. }
  606. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  607. internal struct ExtensionSubstFormat
  608. {
  609. [FieldOffset(0)]
  610. public ushort SubstFormat;
  611. [FieldOffset(2)]
  612. public ushort ExtensionLookupType;
  613. [FieldOffset(4)]
  614. public uint ExtensionOffset;
  615. public override string ToString()
  616. {
  617. return ((LookupTypes)ExtensionLookupType).ToString();
  618. }
  619. }
  620. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  621. internal struct LigatureSubst
  622. {
  623. [FieldOffset(0)]
  624. public ushort SubstFormat; // Format identifier-format = 1
  625. [FieldOffset(2)]
  626. public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
  627. [FieldOffset(4)]
  628. public ushort LigSetCount; // Number of LigatureSet tables
  629. // public ushort [LigSetCount] Array of offsets to LigatureSet tables-from beginning of Substitution table-ordered by Coverage Index
  630. }
  631. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  632. internal struct LigatureHeader
  633. {
  634. [FieldOffset(0)]
  635. public ushort LigGlyph; // GlyphID of ligature to substitute
  636. [FieldOffset(2)]
  637. public ushort CompCount; // Number of components in the ligature
  638. }
  639. internal Substitution LoadLigaturesSubtable(IntPtr lookup_entry)
  640. {
  641. LigatureSubst type4 = (LigatureSubst)Marshal.PtrToStructure(lookup_entry, typeof(LigatureSubst));
  642. type4.SubstFormat = SwapUInt16(type4.SubstFormat);
  643. type4.Coverage = SwapUInt16(type4.Coverage);
  644. type4.LigSetCount = SwapUInt16(type4.LigSetCount);
  645. //To do not null
  646. //LoadCoverageTable(null, Increment(lookup_entry, type4.Coverage));
  647. Coverage coverage = LoadCoverage(Increment(lookup_entry, type4.Coverage));
  648. // Ligature Set
  649. IntPtr ligature_set_ptr = Increment(lookup_entry, Marshal.SizeOf(type4));
  650. IntPtr current_ptr = ligature_set_ptr;
  651. IntPtr[] LigatureSet = new IntPtr[type4.LigSetCount];
  652. LigatureSet[][] ligatureSets = new LigatureSet[type4.LigSetCount][];
  653. for (int i = 0; i < type4.LigSetCount; i++)
  654. {
  655. ushort offset = SwapUInt16((ushort)Marshal.PtrToStructure(current_ptr, typeof(ushort)));
  656. // Console.WriteLine("LigatresSet[" + i + "] at" + offset);
  657. LigatureSet[i] = Increment(lookup_entry, offset);
  658. // Ligature Table
  659. ushort LigatureCount = SwapUInt16((ushort)Marshal.PtrToStructure(LigatureSet[i], typeof(ushort)));
  660. IntPtr ligature_ptr = Increment(LigatureSet[i], sizeof(ushort));
  661. IntPtr[] LigaturePtrs = new IntPtr[LigatureCount];
  662. LigatureHeader[] lh = new LigatureHeader[LigatureCount];
  663. ligatureSets[i] = new LigatureSet[LigatureCount];
  664. for (int j = 0; j < LigatureCount; j++)
  665. {
  666. ushort lig_offset = SwapUInt16((ushort)Marshal.PtrToStructure(ligature_ptr, typeof(ushort)));
  667. LigaturePtrs[j] = Increment(LigatureSet[i], lig_offset);
  668. // Console.WriteLine("\tLigature[" + j + "] at " + lig_offset);
  669. //// Ligature
  670. lh[j] = (LigatureHeader)Marshal.PtrToStructure(LigaturePtrs[j], typeof(LigatureHeader));
  671. lh[j].LigGlyph = SwapUInt16(lh[j].LigGlyph);
  672. lh[j].CompCount = SwapUInt16(lh[j].CompCount);
  673. ushort[] glyphs = new ushort[lh[j].CompCount - 1];
  674. IntPtr ligature_array = Increment(LigaturePtrs[j], Marshal.SizeOf(lh[j]));
  675. for (int k = 0; k < lh[j].CompCount - 1; k++)
  676. {
  677. glyphs[k] = SwapUInt16((ushort)Marshal.PtrToStructure(ligature_array, typeof(ushort)));
  678. ligature_array = Increment(ligature_array, Marshal.SizeOf(glyphs[k]));
  679. }
  680. //// ---------
  681. ligatureSets[i][j] = new LigatureSet(lh[j].LigGlyph, glyphs);
  682. ligature_ptr = Increment(ligature_ptr, sizeof(ushort));
  683. }
  684. // -----------------
  685. current_ptr = Increment(current_ptr, sizeof(ushort));
  686. }
  687. return new Ligature(coverage, ligatureSets);
  688. }
  689. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  690. internal struct CoverageHeader
  691. {
  692. [FieldOffset(0)]
  693. public ushort CoverageFormat; // Format identifier-format = 1
  694. [FieldOffset(2)]
  695. public ushort GlyphCount; // Number of glyphs in the GlyphArray
  696. }
  697. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  698. public struct RangeRecord
  699. {
  700. [FieldOffset(0)]
  701. public ushort Start; // First GlyphID in the range
  702. [FieldOffset(2)]
  703. public ushort End; // Last GlyphID in the range
  704. [FieldOffset(4)]
  705. public ushort StartCoverageIndex; // Coverage Index of first GlyphID in range
  706. }
  707. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  708. internal struct SignleSubstitutionFormat1
  709. {
  710. [FieldOffset(0)]
  711. public ushort SubstFormat; // Format identifier-format = 1
  712. [FieldOffset(2)]
  713. public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
  714. [FieldOffset(4)]
  715. public short DeltaGlyphID; // Add to original GlyphID to get substitute GlyphID
  716. }
  717. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  718. internal struct MultipleSubstFormat1
  719. {
  720. [FieldOffset(0)]
  721. public ushort SubstFormat; // Format identifier-format = 1
  722. [FieldOffset(2)]
  723. public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
  724. [FieldOffset(4)]
  725. public ushort SequenceCount; // Number of Sequence table offsets in the Sequence array
  726. //[FieldOffset(6)]
  727. //public ushort SequenceOffset; // Array of offsets to Sequence tables-from beginning of Substitution table-ordered by Coverage Index
  728. }
  729. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  730. internal struct ContextSubstFormat1
  731. {
  732. [FieldOffset(0)]
  733. public ushort SubstFormat; // Format identifier-format = 1
  734. [FieldOffset(2)]
  735. public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
  736. [FieldOffset(4)]
  737. public ushort SubRuleSetCount; // Number of SubRuleSet tables — must equal glyphCount in Coverage table
  738. //[FieldOffset(6)]
  739. //public ushort[] subRuleSetOffsets; // Array of offsets to SubRuleSet tables. Offsets are from beginning of substitution subtable, ordered by Coverage index
  740. }
  741. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  742. internal struct ContextSubstFormat2
  743. {
  744. [FieldOffset(0)]
  745. public ushort SubstFormat; // Format identifier-format = 1
  746. [FieldOffset(2)]
  747. public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
  748. [FieldOffset(4)]
  749. public ushort ClassDefOffset; // Offset to glyph ClassDef table, from beginning of substitution subtable
  750. [FieldOffset(6)]
  751. public ushort SubClassSetCount; // Number of SubClassSet tables
  752. //[FieldOffset(8)]
  753. //public ushort[] subClassSetOffsets; // Array of offsets to SubClassSet tables. Offsets are from beginning of substitution subtable, ordered by class (may be NULL).
  754. }
  755. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  756. internal struct ContextSubstFormat3
  757. {
  758. [FieldOffset(0)]
  759. public ushort SubstFormat; // Format identifier-format = 1
  760. [FieldOffset(2)]
  761. public ushort GlyphCount; // Number of glyphs in the input glyph sequence
  762. [FieldOffset(4)]
  763. public ushort SubstitutionCount; // Number of SubstLookupRecords
  764. /*
  765. Offset16 coverageOffsets[glyphCount] Array of offsets to Coverage tables. Offsets are from beginning of substitution subtable, in glyph sequence order.
  766. SubstLookupRecord substLookupRecords[substitutionCount] Array of SubstLookupRecords, in design order.
  767. */
  768. }
  769. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  770. internal struct SubClassRule
  771. {
  772. [FieldOffset(0)]
  773. public ushort ClassCount;//GlyphCount; // Total number of classes specified for the context in the rule — includes the first class
  774. [FieldOffset(2)]
  775. public ushort SubstitutionCount; // Number of SubstLookupRecords
  776. /*
  777. uint16 inputSequence[glyphCount - 1] Array of classes to be matched to the input glyph sequence, beginning with the second glyph position.
  778. SubstLookupRecord substLookupRecords[substitutionCount] Array of Substitution lookups, in design order.
  779. */
  780. }
  781. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  782. public struct SubstLookupRecord
  783. {
  784. [FieldOffset(0)]
  785. public ushort GlyphSequenceIndex; // Index into current glyph sequence — first glyph = 0.
  786. [FieldOffset(2)]
  787. public ushort LookupListIndex; // Lookup to apply to that position — zero-based index.
  788. }
  789. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  790. internal struct SubRuleTable
  791. {
  792. [FieldOffset(0)]
  793. public ushort GlyphCount; // Total number of glyphs in input glyph sequence — includes the first glyph.
  794. [FieldOffset(2)]
  795. public ushort SubstitutionCount; // Number of SubstLookupRecords
  796. //[FieldOffset(4)]
  797. //public ushort inputSequence; // [glyphCount - 1] Array of input glyph IDs — start with second glyph
  798. //[FieldOffset(6)]
  799. //public SubstLookupRecord[] substLookupRecords; // [substitutionCount] Array of SubstLookupRecords, in design order
  800. }
  801. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  802. internal struct SequenceFormat
  803. {
  804. [FieldOffset(0)]
  805. public ushort GlyphCount; // Number of glyph IDs in the Substitute array. This should always be greater than 0.
  806. // Substitute [GlyphCount] String of glyph IDs to substitute
  807. }
  808. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  809. internal struct ClassDefFormat1
  810. {
  811. [FieldOffset(0)]
  812. public ushort ClassFormat; // Format identifier — format = 1
  813. [FieldOffset(2)]
  814. public ushort StartGlyphID; // First glyph ID of the classValueArray
  815. [FieldOffset(4)]
  816. public ushort GlyphCount; // Size of the classValueArray
  817. //[FieldOffset(6)]
  818. //public ushort[] classValueArray; // [glyphCount] Array of Class Values — one per glyph ID
  819. }
  820. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  821. internal struct ClassDefFormat2
  822. {
  823. [FieldOffset(0)]
  824. public ushort ClassFormat; // Format identifier — format = 1
  825. [FieldOffset(2)]
  826. public ushort ClassRangeCount; // First glyph ID of the classValueArray
  827. //[FieldOffset(4)]
  828. //public ClassRangeRecord[] classRangeRecords; // Array of ClassRangeRecords — ordered by startGlyphID
  829. }
  830. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  831. public struct ClassRangeRecord
  832. {
  833. [FieldOffset(0)]
  834. public ushort StartGlyphID; // Format identifier — format = 1
  835. [FieldOffset(2)]
  836. public ushort EndGlyphID; // First glyph ID of the classValueArray
  837. [FieldOffset(4)]
  838. public ushort ClassValue; // Array of ClassRangeRecords — ordered by startGlyphID
  839. }
  840. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  841. internal struct ChainContextSubstFormat1
  842. {
  843. [FieldOffset(0)]
  844. public ushort SubstFormat; // Format identifier: format = 1
  845. [FieldOffset(2)]
  846. public ushort Coverage; // Offset to Coverage table, from beginning of substitution subtable.
  847. [FieldOffset(4)]
  848. public ushort ChainSubRuleSetCount; // Number of ChainSubRuleSet tables — must equal GlyphCount in Coverage table.
  849. /*
  850. Offset16 chainSubRuleSetOffsets[chainSubRuleSetCount] Array of offsets to ChainSubRuleSet tables. Offsets are from beginning of substitution subtable, ordered by Coverage index.
  851. */
  852. }
  853. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  854. internal struct ChainContextSubstFormat2
  855. {
  856. [FieldOffset(0)]
  857. public ushort SubstFormat; // Format identifier: format = 2
  858. [FieldOffset(2)]
  859. public ushort Coverage; // Offset to Coverage table, from beginning of substitution subtable.
  860. [FieldOffset(4)]
  861. public ushort BacktrackClassDefOffset; // Offset to glyph ClassDef table containing backtrack sequence data, from beginning of substitution subtable.
  862. [FieldOffset(6)]
  863. public ushort InputClassDefOffset; // Offset to glyph ClassDef table containing input sequence data, from beginning of substitution subtable.
  864. [FieldOffset(8)]
  865. public ushort LookaheadClassDefOffset; // Offset to glyph ClassDef table containing lookahead sequence data, from beginning of substitution subtable.
  866. [FieldOffset(10)]
  867. public ushort ChainSubClassSetCount; // Number of ChainSubClassSet tables
  868. /*
  869. Offset16 chainSubClassSetOffsets[chainSubClassSetCount] Array of offsets to ChainSubClassSet tables. Offsets are from beginning of substitution subtable, ordered by input class (may be NULL)
  870. */
  871. }
  872. [StructLayout(LayoutKind.Explicit, Pack = 1)]
  873. internal struct ChainContextSubstFormat3
  874. {
  875. [FieldOffset(0)]
  876. public ushort SubstFormat; // Format identifier: format = 3
  877. /*
  878. uint16 backtrackGlyphCount Number of glyphs in the backtracking sequence.
  879. Offset16 backtrackCoverageOffsets[backtrackGlyphCount] Array of offsets to coverage tables in backtracking sequence. Offsets are from beginning of substition subtable, in glyph sequence order.
  880. uint16 inputGlyphCount Number of glyphs in input sequence
  881. Offset16 inputCoverageOffsets[inputGlyphCount] Array of offsets to coverage tables in input sequence. Offsets are from beginning of substition subtable, in glyph sequence order.
  882. uint16 lookaheadGlyphCount Number of glyphs in lookahead sequence
  883. Offset16 lookaheadCoverageOffsets[lookaheadGlyphCount] Array of offsets to coverage tables in lookahead sequence. Offsets are from beginning of substitution subtable, in glyph sequence order.
  884. uint16 substitutionCount Number of SubstLookupRecords
  885. SubstLookupRecord substLookupRecords[substitutionCount] Array of SubstLookupRecords, in design order
  886. */
  887. }
  888. private Substitution LoadChainingContextSubstFormat1(IntPtr lookup_entry)
  889. {
  890. ChainContextSubstFormat1 type1 = (ChainContextSubstFormat1)Marshal.PtrToStructure(lookup_entry, typeof(ChainContextSubstFormat1));
  891. type1.SubstFormat = SwapUInt16(type1.SubstFormat);
  892. type1.ChainSubRuleSetCount = SwapUInt16(type1.ChainSubRuleSetCount);
  893. type1.Coverage = SwapUInt16(type1.Coverage);
  894. ChainingContextual1.ChainSubRule[][] chainSubRuleSets
  895. = new ChainingContextual1.ChainSubRule[type1.ChainSubRuleSetCount][];
  896. IntPtr chain_sub_rule_set_offsets = Increment(lookup_entry, Marshal.SizeOf(type1));
  897. for (int i = 0; i < type1.ChainSubRuleSetCount; i++)
  898. {
  899. ushort offset = (ushort)Marshal.PtrToStructure(chain_sub_rule_set_offsets, typeof(ushort));
  900. offset = SwapUInt16(offset);
  901. IntPtr chain_sub_rule_set_table = Increment(lookup_entry, offset);
  902. ushort count = (ushort)Marshal.PtrToStructure(chain_sub_rule_set_table, typeof(ushort));
  903. count = SwapUInt16(count);
  904. IntPtr chain_sub_rule_offset = Increment(chain_sub_rule_set_table, Marshal.SizeOf(count));
  905. ChainingContextual1.ChainSubRule[] chainSubRuleSet = new ChainingContextual1.ChainSubRule[count];
  906. for (int j = 0; j < count; j++)
  907. {
  908. ushort offset2 = (ushort)Marshal.PtrToStructure(chain_sub_rule_offset, typeof(ushort));
  909. offset2 = SwapUInt16(offset2);
  910. IntPtr chain_sub_rule_table = Increment(chain_sub_rule_set_table, offset2);
  911. IntPtr chain_sub_rule_arrays = chain_sub_rule_table;
  912. //start array
  913. ushort backtrackGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  914. backtrackGlyphCount = SwapUInt16(backtrackGlyphCount);
  915. ushort[] backtrackSequence = new ushort[backtrackGlyphCount];
  916. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(backtrackGlyphCount));
  917. for (int k = 0; k < backtrackGlyphCount; k++)
  918. {
  919. ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  920. glyph = SwapUInt16(glyph);
  921. backtrackSequence[k] = glyph;
  922. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
  923. }
  924. //end array
  925. //start array
  926. ushort inputGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  927. inputGlyphCount = SwapUInt16(inputGlyphCount);
  928. ushort[] inputSequence = new ushort[inputGlyphCount - 1];
  929. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(inputGlyphCount));
  930. for (int k = 0; k < inputGlyphCount - 1; k++)
  931. {
  932. ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  933. glyph = SwapUInt16(glyph);
  934. inputSequence[k] = glyph;
  935. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
  936. }
  937. //end array
  938. //start array
  939. ushort lookaheadGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  940. lookaheadGlyphCount = SwapUInt16(lookaheadGlyphCount);
  941. ushort[] lookAheadSequence = new ushort[lookaheadGlyphCount];
  942. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(lookaheadGlyphCount));
  943. for (int k = 0; k < lookaheadGlyphCount; k++)
  944. {
  945. ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  946. glyph = SwapUInt16(glyph);
  947. lookAheadSequence[k] = glyph;
  948. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
  949. }
  950. //end array
  951. //start array
  952. ushort substitutionCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  953. substitutionCount = SwapUInt16(substitutionCount);
  954. SubstLookupRecord[] records = new SubstLookupRecord[substitutionCount];
  955. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(substitutionCount));
  956. for (int k = 0; k < substitutionCount; k++)
  957. {
  958. SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(SubstLookupRecord));
  959. record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
  960. record.LookupListIndex = SwapUInt16(record.LookupListIndex);
  961. records[k] = record;
  962. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(record));
  963. }
  964. //end array
  965. chainSubRuleSet[j] = new ChainingContextual1.ChainSubRule(backtrackSequence, inputSequence, lookAheadSequence, records);
  966. chain_sub_rule_offset = Increment(chain_sub_rule_offset, Marshal.SizeOf(offset2));
  967. }
  968. chainSubRuleSets[i] = chainSubRuleSet;
  969. chain_sub_rule_set_offsets = Increment(chain_sub_rule_set_offsets, Marshal.SizeOf(offset));
  970. }
  971. return new ChainingContextual1(this, LoadCoverage(Increment(lookup_entry, type1.Coverage)), chainSubRuleSets);
  972. }
  973. private Substitution LoadChainingContextSubstFormat2(IntPtr lookup_entry)
  974. {
  975. ChainContextSubstFormat2 type2 = (ChainContextSubstFormat2)Marshal.PtrToStructure(lookup_entry, typeof(ChainContextSubstFormat2));
  976. type2.SubstFormat = SwapUInt16(type2.SubstFormat);
  977. type2.Coverage = SwapUInt16(type2.Coverage);
  978. type2.BacktrackClassDefOffset = SwapUInt16(type2.BacktrackClassDefOffset);
  979. type2.InputClassDefOffset = SwapUInt16(type2.InputClassDefOffset);
  980. type2.LookaheadClassDefOffset = SwapUInt16(type2.LookaheadClassDefOffset);
  981. type2.ChainSubClassSetCount = SwapUInt16(type2.ChainSubClassSetCount);
  982. IntPtr chain_sub_class_set_offsets = Increment(lookup_entry, Marshal.SizeOf(type2));
  983. ChainingContextual2.ChainSubClassRule[][] chainSubClassRuleSets
  984. = new ChainingContextual2.ChainSubClassRule[type2.ChainSubClassSetCount][];
  985. for (int i = 0; i < type2.ChainSubClassSetCount; i++)
  986. {
  987. ushort offset = (ushort)Marshal.PtrToStructure(chain_sub_class_set_offsets, typeof(ushort));
  988. offset = SwapUInt16(offset);
  989. if(offset == 0)
  990. {
  991. chain_sub_class_set_offsets = Increment(chain_sub_class_set_offsets, Marshal.SizeOf(offset));
  992. continue;
  993. }
  994. IntPtr chain_sub_class_set_table = Increment(lookup_entry, offset);
  995. ushort count = (ushort)Marshal.PtrToStructure(chain_sub_class_set_table, typeof(ushort));
  996. count = SwapUInt16(count);
  997. IntPtr chain_sub_class_offset = Increment(chain_sub_class_set_table, Marshal.SizeOf(count));
  998. ChainingContextual2.ChainSubClassRule[] chainSubClassSet = new ChainingContextual2.ChainSubClassRule[count];
  999. for (int j = 0; j < count; j++)
  1000. {
  1001. ushort offset2 = (ushort)Marshal.PtrToStructure(chain_sub_class_offset, typeof(ushort));
  1002. offset2 = SwapUInt16(offset2);
  1003. IntPtr chain_sub_rule_table = Increment(chain_sub_class_set_table, offset2);
  1004. IntPtr chain_sub_rule_arrays = chain_sub_rule_table;
  1005. //start array
  1006. ushort backtrackGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  1007. backtrackGlyphCount = SwapUInt16(backtrackGlyphCount);
  1008. ushort[] backtrackSequence = new ushort[backtrackGlyphCount];
  1009. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(backtrackGlyphCount));
  1010. for (int k = 0; k < backtrackGlyphCount; k++)
  1011. {
  1012. ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  1013. glyph = SwapUInt16(glyph);
  1014. backtrackSequence[k] = glyph;
  1015. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
  1016. }
  1017. //end array
  1018. //start array
  1019. ushort inputGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  1020. inputGlyphCount = SwapUInt16(inputGlyphCount);
  1021. ushort[] inputSequence = new ushort[inputGlyphCount - 1];
  1022. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(inputGlyphCount));
  1023. for (int k = 0; k < inputGlyphCount - 1; k++)
  1024. {
  1025. ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  1026. glyph = SwapUInt16(glyph);
  1027. inputSequence[k] = glyph;
  1028. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
  1029. }
  1030. //end array
  1031. //start array
  1032. ushort lookaheadGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  1033. lookaheadGlyphCount = SwapUInt16(lookaheadGlyphCount);
  1034. ushort[] lookAheadSequence = new ushort[lookaheadGlyphCount];
  1035. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(lookaheadGlyphCount));
  1036. for (int k = 0; k < lookaheadGlyphCount; k++)
  1037. {
  1038. ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  1039. glyph = SwapUInt16(glyph);
  1040. lookAheadSequence[k] = glyph;
  1041. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
  1042. }
  1043. //end array
  1044. //start array
  1045. ushort substitutionCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
  1046. substitutionCount = SwapUInt16(substitutionCount);
  1047. SubstLookupRecord[] records = new SubstLookupRecord[substitutionCount];
  1048. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(substitutionCount));
  1049. for (int k = 0; k < substitutionCount; k++)
  1050. {
  1051. SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(SubstLookupRecord));
  1052. record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
  1053. record.LookupListIndex = SwapUInt16(record.LookupListIndex);
  1054. records[k] = record;
  1055. chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(record));
  1056. }
  1057. //end array
  1058. chainSubClassSet[j] = new ChainingContextual2.ChainSubClassRule(backtrackSequence, inputSequence, lookAheadSequence, records);
  1059. chain_sub_class_offset = Increment(chain_sub_class_offset, Marshal.SizeOf(offset2));
  1060. }
  1061. chainSubClassRuleSets[i] = chainSubClassSet;
  1062. chain_sub_class_set_offsets = Increment(chain_sub_class_set_offsets, Marshal.SizeOf(offset));
  1063. }
  1064. return new ChainingContextual2(this, chainSubClassRuleSets,
  1065. LoadCoverage(Increment(lookup_entry, type2.Coverage)),
  1066. LoadClassDefinition(Increment(lookup_entry, type2.BacktrackClassDefOffset)),
  1067. LoadClassDefinition(Increment(lookup_entry, type2.InputClassDefOffset)),
  1068. LoadClassDefinition(Increment(lookup_entry, type2.LookaheadClassDefOffset)));
  1069. }
  1070. private Substitution LoadChainingContextSubstFormat3(IntPtr lookup_entry)
  1071. {
  1072. IntPtr chain_format_3_array = Increment(lookup_entry, Marshal.SizeOf(typeof(ushort)));
  1073. //start array
  1074. ushort backtrackGlyphCount = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
  1075. backtrackGlyphCount = SwapUInt16(backtrackGlyphCount);
  1076. Coverage[] backtrackSequence = new Coverage[backtrackGlyphCount];
  1077. chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(backtrackGlyphCount));
  1078. for (int k = 0; k < backtrackGlyphCount; k++)
  1079. {
  1080. ushort offset = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
  1081. offset = SwapUInt16(offset);
  1082. backtrackSequence[k] = LoadCoverage(Increment(lookup_entry, offset));
  1083. chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(offset));
  1084. }
  1085. //end array
  1086. //start array
  1087. ushort inputGlyphCount = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
  1088. inputGlyphCount = SwapUInt16(inputGlyphCount);
  1089. Coverage[] inputSequence = new Coverage[inputGlyphCount];
  1090. chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(inputGlyphCount));
  1091. for (int k = 0; k < inputGlyphCount; k++)
  1092. {
  1093. ushort offset = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
  1094. offset = SwapUInt16(offset);
  1095. inputSequence[k] = LoadCoverage(Increment(lookup_entry, offset));
  1096. chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(offset));
  1097. }
  1098. //end array
  1099. //start array
  1100. ushort lookaheadGlyphCount = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
  1101. lookaheadGlyphCount = SwapUInt16(lookaheadGlyphCount);
  1102. Coverage[] lookAheadSequence = new Coverage[lookaheadGlyphCount];
  1103. chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(lookaheadGlyphCount));
  1104. for (int k = 0; k < lookaheadGlyphCount; k++)
  1105. {
  1106. ushort offset = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
  1107. offset = SwapUInt16(offset);
  1108. lookAheadSequence[k] = LoadCoverage(Increment(lookup_entry, offset));
  1109. chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(offset));
  1110. }
  1111. //end array
  1112. //start array
  1113. ushort substitutionCount = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
  1114. substitutionCount = SwapUInt16(substitutionCount);
  1115. SubstLookupRecord[] records = new SubstLookupRecord[substitutionCount];
  1116. chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(substitutionCount));
  1117. for (int k = 0; k < substitutionCount; k++)
  1118. {
  1119. SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(chain_format_3_array, typeof(SubstLookupRecord));
  1120. record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
  1121. record.LookupListIndex = SwapUInt16(record.LookupListIndex);
  1122. records[k] = record;
  1123. chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(record));
  1124. }
  1125. //end array
  1126. return new ChainingContextual3(this, records, backtrackSequence, inputSequence, lookAheadSequence);
  1127. }
  1128. #if DEBUG_TTF
  1129. static int debug = 0;
  1130. #endif
  1131. //[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
  1132. [System.Security.SecurityCritical]
  1133. private Substitution LoadChainingContext(IntPtr lookup_entry)
  1134. {
  1135. try
  1136. {
  1137. ushort format = (ushort)Marshal.PtrToStructure(lookup_entry, typeof(ushort));
  1138. format = SwapUInt16(format);
  1139. #if DEBUG_TTF
  1140. debug++;
  1141. Console.WriteLine("LoadChainingContext format" + format.ToString() + " Iteration " + debug.ToString());
  1142. if (debug == 123)
  1143. ;
  1144. #endif
  1145. switch (format)
  1146. {
  1147. case 1:
  1148. return LoadChainingContextSubstFormat1(lookup_entry);
  1149. case 2:
  1150. return LoadChainingContextSubstFormat2(lookup_entry);
  1151. case 3:
  1152. return LoadChainingContextSubstFormat3(lookup_entry);
  1153. default:
  1154. throw new NotSupportedException("Format of ChaingContext");
  1155. }
  1156. }
  1157. catch (System.AccessViolationException e)
  1158. {
  1159. Console.WriteLine(e.StackTrace);
  1160. }
  1161. return new VoidSubstitution();
  1162. }
  1163. //[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
  1164. [System.Security.SecurityCritical]
  1165. internal override void Load(IntPtr font)
  1166. {
  1167. try
  1168. {
  1169. gsub_ptr = Increment(font, (int)this.Offset);
  1170. header = (GSUB_Header)Marshal.PtrToStructure(gsub_ptr, typeof(GSUB_Header));
  1171. ChangeEndian();
  1172. LoadLookupList();
  1173. LoadScriptList();
  1174. //if(do_features) LoadFeatureList();
  1175. #if DEBUG_TTF
  1176. Console.WriteLine("=====================================================");
  1177. #endif
  1178. }
  1179. catch (System.Exception e)
  1180. {
  1181. throw e;
  1182. }
  1183. //foreach (DictionaryEntry script in script_list)
  1184. //{
  1185. // Console.WriteLine(script.Key);
  1186. // foreach (DictionaryEntry language in script.Value as Hashtable)
  1187. // {
  1188. // if (language.Key != "")
  1189. // Console.WriteLine("\t" + language.Key);
  1190. // else
  1191. // Console.WriteLine("\tDEFAULT");
  1192. // foreach (DictionaryEntry features in language.Value as Hashtable)
  1193. // {
  1194. // Console.WriteLine("\t\t" + features.Key /*+ "--> LookupTypes:" */ );
  1195. // foreach (ushort offset in features.Value as ushort[])
  1196. // {
  1197. // LookupEntry le = (LookupEntry)lookup_list[offset];
  1198. // // for (int i = 0; i < le.record_header.SubTableCount; i++)
  1199. // {
  1200. // Console.Write("\t\t\t");
  1201. // switch ((LookupTypes)le.record_header.LookupType)
  1202. // {
  1203. // case LookupTypes.Single:
  1204. // Console.WriteLine("Single");
  1205. // break;
  1206. // case LookupTypes.Multiple:
  1207. // Console.WriteLine("Multiple");
  1208. // break;
  1209. // case LookupTypes.Alternate:
  1210. // Console.WriteLine("Alternate");
  1211. // break;
  1212. // case LookupTypes.Ligature:
  1213. // Console.WriteLine("Ligature");
  1214. // break;
  1215. // case LookupTypes.Context:
  1216. // Console.WriteLine("Context");
  1217. // break;
  1218. // case LookupTypes.ChainingContext:
  1219. // Console.WriteLine("ChainingContext");
  1220. // break;
  1221. // case LookupTypes.ExtensionSubstitution:
  1222. // Console.WriteLine("ExtensionSubstitution");
  1223. // break;
  1224. // case LookupTypes.ReverseChainingContextSingle:
  1225. // Console.WriteLine("ReverseChainingContextSingle");
  1226. // break;
  1227. // default:
  1228. // Console.WriteLine("!!! Unknown lookup type");
  1229. // break;
  1230. // }
  1231. // }
  1232. // }
  1233. // }
  1234. // }
  1235. //}
  1236. //Console.WriteLine("=====================================================");
  1237. }
  1238. internal override uint Save(IntPtr font, uint offset)
  1239. {
  1240. this.Offset = offset;
  1241. return base.Save(font, offset);
  1242. }
  1243. private void ChangeEndian()
  1244. {
  1245. header.Version = SwapUInt32(header.Version);
  1246. header.ScriptList = SwapUInt16(header.ScriptList);
  1247. header.LookupList = SwapUInt16(header.LookupList);
  1248. header.FeatureList = SwapUInt16(header.FeatureList);
  1249. }
  1250. public GlyphSubstitutionClass(TrueTypeTable src) : base(src) { }
  1251. internal List<ushort> ApplyGlyph(string script, string lang, ushort[] chars)
  1252. {
  1253. if (script == null)
  1254. {
  1255. script = "latn";
  1256. foreach (string name in script_list.Keys)
  1257. {
  1258. script = name;
  1259. break;
  1260. }
  1261. }
  1262. if (script_list.ContainsKey(script))
  1263. {
  1264. Hashtable lang_sys_hash = script_list[script] as Hashtable;
  1265. Hashtable lang_sys = null;
  1266. if (lang_sys_hash.ContainsKey(lang))
  1267. {
  1268. lang_sys = lang_sys_hash[lang] as Hashtable;
  1269. }
  1270. else if (lang_sys_hash.ContainsKey(string.Empty))
  1271. {
  1272. lang_sys = lang_sys_hash[string.Empty] as Hashtable;
  1273. }
  1274. if (lang_sys != null)
  1275. {
  1276. switch (script)
  1277. {
  1278. case "arab":
  1279. return ApplyGlyphArabic(lang_sys, chars);
  1280. }
  1281. }
  1282. }
  1283. return new List<ushort>(chars);
  1284. }
  1285. private void ApplyGlyphFeature(List<ushort> result, ushort[] offsets, ushort[] chars, ref int i)
  1286. {
  1287. foreach (ushort offset in offsets)
  1288. {
  1289. LookupEntry le = lookup_list[offset];
  1290. for (int j = 0; j < le.subs.Length; j++)
  1291. if (le.subs[j].Apply(result, chars, ref i))
  1292. return;
  1293. }
  1294. result.Add(chars[i]);
  1295. }
  1296. private bool IsApplyGlyphFeature(int index, ushort[] offsets, ushort[] chars)
  1297. {
  1298. if (index < 0) return false;
  1299. if (index >= chars.Length) return false;
  1300. foreach (ushort offset in offsets)
  1301. {
  1302. LookupEntry le = lookup_list[offset];
  1303. for (int j = 0; j < le.subs.Length; j++)
  1304. if (le.subs[j].IsApply(chars, index) >= 0)
  1305. return true;
  1306. }
  1307. return false;
  1308. }
  1309. private List<ushort> ApplyGlyphArabic(Hashtable lang_sys, ushort[] chars)
  1310. {
  1311. List<ushort> result = new List<ushort>();
  1312. if (lang_sys.Contains("ccmp"))
  1313. {
  1314. ushort[] ccmp = lang_sys["ccmp"] as ushort[];
  1315. for (int i = 0; i < chars.Length; i++)
  1316. {
  1317. ApplyGlyphFeature(result, ccmp, chars, ref i);
  1318. }
  1319. chars = result.ToArray();
  1320. result.Clear();
  1321. }
  1322. ushort[] isol;
  1323. if (lang_sys.Contains("isol")) isol = lang_sys["isol"] as ushort[];
  1324. else isol = new ushort[0];
  1325. ushort[] init;
  1326. if (lang_sys.Contains("init")) init = lang_sys["init"] as ushort[];
  1327. else init = new ushort[0];
  1328. ushort[] medi;
  1329. if (lang_sys.Contains("medi")) medi = lang_sys["medi"] as ushort[];
  1330. else medi = new ushort[0];
  1331. ushort[] fina;
  1332. if (lang_sys.Contains("fina")) fina = lang_sys["fina"] as ushort[];
  1333. else fina = new ushort[0];
  1334. ArabicCharType[] types = new ArabicCharType[chars.Length];
  1335. //Ýòî êîñòûëü, òàê êàê ÿ íå çíàþ êàêèì îáðàçîì âûòàùèòü íóæíûå èíäåêñû, ñäåëàþ òàêîé âàðèàíò áóäó ãóãëèòü
  1336. for (int i = 0; i < chars.Length; i++)
  1337. {
  1338. bool nextMedi = IsApplyGlyphFeature(i + 1, medi, chars);
  1339. bool nextFina = IsApplyGlyphFeature(i + 1, fina, chars);
  1340. bool prevMedi = IsApplyGlyphFeature(i - 1, medi, chars);
  1341. bool prevInit = IsApplyGlyphFeature(i - 1, init, chars);
  1342. if (nextMedi || nextFina)
  1343. {
  1344. if (prevMedi || prevInit)
  1345. {
  1346. bool curMedi = IsApplyGlyphFeature(i, medi, chars);
  1347. if (curMedi)
  1348. {
  1349. types[i] = ArabicCharType.Medi;
  1350. continue;
  1351. }
  1352. }
  1353. else
  1354. {
  1355. bool curInit = IsApplyGlyphFeature(i, init, chars);
  1356. if (curInit)
  1357. {
  1358. types[i] = ArabicCharType.Init;
  1359. continue;
  1360. }
  1361. }
  1362. types[i] = ArabicCharType.None;
  1363. continue;
  1364. }
  1365. if (prevInit || prevMedi)
  1366. {
  1367. bool curFina = IsApplyGlyphFeature(i, fina, chars);
  1368. if (curFina)
  1369. {
  1370. types[i] = ArabicCharType.Fina;
  1371. continue;
  1372. }
  1373. types[i] = ArabicCharType.None;
  1374. continue;
  1375. }
  1376. if (!nextMedi && !nextFina && !prevInit && !prevMedi)
  1377. {
  1378. bool curIsol = IsApplyGlyphFeature(i, isol, chars);
  1379. if (curIsol)
  1380. {
  1381. types[i] = ArabicCharType.Isol;
  1382. continue;
  1383. }
  1384. types[i] = ArabicCharType.None;
  1385. continue;
  1386. }
  1387. types[i] = ArabicCharType.None;
  1388. }
  1389. for (int i = 0; i < chars.Length; i++)
  1390. {
  1391. switch (types[i])
  1392. {
  1393. case ArabicCharType.None:
  1394. result.Add(chars[i]);
  1395. break;
  1396. case ArabicCharType.Isol:
  1397. ApplyGlyphFeature(result, isol, chars, ref i);
  1398. break;
  1399. case ArabicCharType.Fina:
  1400. ApplyGlyphFeature(result, fina, chars, ref i);
  1401. break;
  1402. case ArabicCharType.Medi:
  1403. ApplyGlyphFeature(result, medi, chars, ref i);
  1404. break;
  1405. case ArabicCharType.Init:
  1406. ApplyGlyphFeature(result, init, chars, ref i);
  1407. break;
  1408. }
  1409. }
  1410. chars = result.ToArray();
  1411. result.Clear();
  1412. if (lang_sys.Contains("rlig"))
  1413. {
  1414. ushort[] rlig = lang_sys["rlig"] as ushort[];
  1415. for (int i = 0; i < chars.Length; i++)
  1416. {
  1417. ApplyGlyphFeature(result, rlig, chars, ref i);
  1418. }
  1419. chars = result.ToArray();
  1420. result.Clear();
  1421. }
  1422. if (lang_sys.Contains("calt"))
  1423. {
  1424. ushort[] calt = lang_sys["calt"] as ushort[];
  1425. for (int i = 0; i < chars.Length; i++)
  1426. {
  1427. ApplyGlyphFeature(result, calt, chars, ref i);
  1428. }
  1429. chars = result.ToArray();
  1430. result.Clear();
  1431. }
  1432. return new List<ushort>(chars);
  1433. }
  1434. enum ArabicCharType
  1435. {
  1436. None, Isol, Init, Medi, Fina
  1437. }
  1438. private ushort[] ApplySubstLookupRecord(ushort[] resultArr, SubstLookupRecord[] records)
  1439. {
  1440. List<ushort> result = new List<ushort>();
  1441. for (int j = 0; j < records.Length; j++)
  1442. {
  1443. result.Clear();
  1444. int resultIndex = 0;
  1445. for (; resultIndex < records[j].GlyphSequenceIndex; resultIndex++)
  1446. result.Add(resultArr[resultIndex]);
  1447. LookupEntry le = lookup_list[records[j].LookupListIndex];
  1448. for (int k = 0; k < le.subs.Length; k++)
  1449. {
  1450. if (le.subs[k].Apply(result, resultArr, ref resultIndex))
  1451. {
  1452. resultIndex += 1;
  1453. break;
  1454. }
  1455. }
  1456. for (; resultIndex < resultArr.Length; resultIndex++)
  1457. result.Add(resultArr[resultIndex]);
  1458. resultArr = result.ToArray();
  1459. }
  1460. return resultArr;
  1461. }
  1462. public interface Substitution
  1463. {
  1464. // need to index = index + step - 1;
  1465. /// <summary>
  1466. /// Return true if was applied
  1467. /// </summary>
  1468. /// <param name="list"></param>
  1469. /// <param name="chars"></param>
  1470. /// <param name="index"></param>
  1471. /// <returns></returns>
  1472. bool Apply(List<ushort> list, ushort[] chars, ref int index);
  1473. /// <summary>
  1474. /// Return coverageIndex for ApplyForce or if fail then return -1
  1475. /// </summary>
  1476. /// <param name="chars"></param>
  1477. /// <param name="index"></param>
  1478. /// <returns></returns>
  1479. int IsApply(ushort[] chars, int index);
  1480. /// <summary>
  1481. /// Apply this Substitution with specified coverageIndex, cant be called only after IsApply
  1482. /// </summary>
  1483. /// <param name="list"></param>
  1484. /// <param name="chars"></param>
  1485. /// <param name="index"></param>
  1486. /// <param name="coverageIndex"></param>
  1487. void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex);
  1488. IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types);
  1489. }
  1490. public interface Coverage
  1491. {
  1492. int IsSubstituteGetIndex(ushort ch);
  1493. ushort[] GetGlyphs();
  1494. ushort GetFirstGlyph();
  1495. }
  1496. public struct Coverage1 : Coverage
  1497. {
  1498. public ushort GlyphCount;
  1499. public ushort[] Glyphs;
  1500. public Coverage1(ushort glyphCount, ushort[] glyphs)
  1501. {
  1502. this.GlyphCount = glyphCount;
  1503. this.Glyphs = glyphs;
  1504. }
  1505. public ushort GetFirstGlyph()
  1506. {
  1507. if (Glyphs.Length > 0)
  1508. return Glyphs[0];
  1509. return 1;
  1510. }
  1511. public ushort[] GetGlyphs()
  1512. {
  1513. return Glyphs;
  1514. }
  1515. public int IsSubstituteGetIndex(ushort ch)
  1516. {
  1517. for (int i = 0; i < GlyphCount; i++)
  1518. {
  1519. if (Glyphs[i] == ch)
  1520. return i;
  1521. }
  1522. return -1;
  1523. }
  1524. }
  1525. public struct Coverage2 : Coverage
  1526. {
  1527. public ushort GlyphCount;
  1528. public RangeRecord[] RangeRecords;
  1529. public Coverage2(ushort glyphCount, RangeRecord[] rangeRecords)
  1530. {
  1531. this.GlyphCount = glyphCount;
  1532. this.RangeRecords = rangeRecords;
  1533. }
  1534. public ushort GetFirstGlyph()
  1535. {
  1536. if (RangeRecords.Length > 0)
  1537. return RangeRecords[0].Start;
  1538. return 1;
  1539. }
  1540. public ushort[] GetGlyphs()
  1541. {
  1542. Dictionary<int, ushort> results = new Dictionary<int, ushort>();
  1543. for (int i = 0; i < RangeRecords.Length; i++)
  1544. {
  1545. for (int j = 0; j + RangeRecords[i].Start <= RangeRecords[i].End; j++)
  1546. {
  1547. results[j + RangeRecords[i].StartCoverageIndex] =
  1548. (ushort)(RangeRecords[i].Start + j);
  1549. }
  1550. }
  1551. ushort[] result = new ushort[results.Count];
  1552. foreach (ushort key in results.Keys)
  1553. {
  1554. result[key] = results[key];
  1555. }
  1556. return result;
  1557. }
  1558. public int IsSubstituteGetIndex(ushort ch)
  1559. {
  1560. //var arr = RangeRecords.Select(a => a).OrderBy(a => a.StartCoverageIndex).ToArray();
  1561. for (int i = 0; i < GlyphCount; i++)
  1562. {
  1563. if (RangeRecords[i].Start <= ch && RangeRecords[i].End >= ch)
  1564. return RangeRecords[i].End - RangeRecords[i].Start + RangeRecords[i].StartCoverageIndex;
  1565. }
  1566. return -1;
  1567. }
  1568. }
  1569. public struct Single1 : Substitution
  1570. {
  1571. public short DeltaGlyphIDOrGlyphCount;
  1572. public Coverage Coverage;
  1573. public Single1(short deltaGlyphID, Coverage coverage)
  1574. {
  1575. this.DeltaGlyphIDOrGlyphCount = deltaGlyphID;
  1576. this.Coverage = coverage;
  1577. }
  1578. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  1579. {
  1580. int index2 = IsApply(chars, index);
  1581. if (index2 >= 0)
  1582. {
  1583. ApplyForce(list, chars, ref index, index2);
  1584. return true;
  1585. }
  1586. return false;
  1587. }
  1588. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  1589. {
  1590. list.Add((ushort)(chars[index] + DeltaGlyphIDOrGlyphCount));
  1591. }
  1592. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  1593. {
  1594. if (types != null && !ExtFor2005.Contains(types, LookupTypes.Single))
  1595. yield break;
  1596. ushort[] glyphs = Coverage.GetGlyphs();
  1597. for (int i = 0; i < glyphs.Length; i++)
  1598. {
  1599. yield return new KeyValuePair<ushort[], ushort[]>(
  1600. new ushort[] { glyphs[i] },
  1601. new ushort[] { (ushort)(glyphs[i] + DeltaGlyphIDOrGlyphCount) }
  1602. );
  1603. }
  1604. }
  1605. public int IsApply(ushort[] chars, int index)
  1606. {
  1607. return Coverage.IsSubstituteGetIndex(chars[index]);
  1608. }
  1609. }
  1610. public struct Single2 : Substitution
  1611. {
  1612. public ushort[] Substitutes;
  1613. public Coverage Coverage;
  1614. public Single2(ushort[] substitutes, Coverage coverage)
  1615. {
  1616. this.Substitutes = substitutes;
  1617. this.Coverage = coverage;
  1618. }
  1619. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  1620. {
  1621. int index2 = IsApply(chars, index);
  1622. if (index2 >= 0)
  1623. {
  1624. ApplyForce(list, chars, ref index, index2);
  1625. return true;
  1626. }
  1627. return false;
  1628. }
  1629. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  1630. {
  1631. list.Add(Substitutes[coverageIndex]);
  1632. }
  1633. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  1634. {
  1635. if (types != null && !ExtFor2005.Contains(types, LookupTypes.Single))
  1636. yield break;
  1637. ushort[] glyphs = Coverage.GetGlyphs();
  1638. for (int i = 0; i < glyphs.Length; i++)
  1639. {
  1640. yield return new KeyValuePair<ushort[], ushort[]>(
  1641. new ushort[] { glyphs[i] },
  1642. new ushort[] { Substitutes[i] }
  1643. );
  1644. }
  1645. }
  1646. public int IsApply(ushort[] chars, int index)
  1647. {
  1648. return Coverage.IsSubstituteGetIndex(chars[index]);
  1649. }
  1650. }
  1651. public struct Multiple : Substitution
  1652. {
  1653. public ushort[][] Sequences;
  1654. public Coverage Coverage;
  1655. public Multiple(ushort[][] sequences, Coverage coverage)
  1656. {
  1657. this.Sequences = sequences;
  1658. this.Coverage = coverage;
  1659. }
  1660. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  1661. {
  1662. int index2 = IsApply(chars, index);
  1663. if (index2 >= 0)
  1664. {
  1665. ApplyForce(list, chars, ref index, index2);
  1666. return true;
  1667. }
  1668. return false;
  1669. }
  1670. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  1671. {
  1672. list.AddRange(Sequences[coverageIndex]);
  1673. }
  1674. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  1675. {
  1676. if (types != null && !ExtFor2005.Contains(types, LookupTypes.Multiple))
  1677. yield break;
  1678. ushort[] glyphs = Coverage.GetGlyphs();
  1679. for (int i = 0; i < glyphs.Length; i++)
  1680. {
  1681. yield return new KeyValuePair<ushort[], ushort[]>(
  1682. new ushort[] { glyphs[i] },
  1683. Sequences[i]);
  1684. }
  1685. }
  1686. public int IsApply(ushort[] chars, int index)
  1687. {
  1688. return Coverage.IsSubstituteGetIndex(chars[index]);
  1689. }
  1690. }
  1691. public struct Ligature : Substitution
  1692. {
  1693. public Coverage Coverage;
  1694. public LigatureSet[][] LigatureSets;
  1695. LigatureSet LastSetIsApply;
  1696. public Ligature(Coverage coverage, LigatureSet[][] ligatureSets)
  1697. {
  1698. this.Coverage = coverage;
  1699. this.LigatureSets = ligatureSets;
  1700. LastSetIsApply = new LigatureSet();
  1701. }
  1702. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  1703. {
  1704. int index2 = IsApply(chars, index);
  1705. if (index2 >= 0)
  1706. {
  1707. ApplyForce(list, chars, ref index, index2);
  1708. return true;
  1709. }
  1710. return false;
  1711. }
  1712. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  1713. {
  1714. index += LastSetIsApply.Components.Length;
  1715. list.Add(LastSetIsApply.LigGlyph);
  1716. }
  1717. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  1718. {
  1719. if (types != null && !ExtFor2005.Contains(types, LookupTypes.Ligature))
  1720. yield break;
  1721. ushort[] glyphs = Coverage.GetGlyphs();
  1722. for (int i = 0; i < glyphs.Length; i++)
  1723. {
  1724. LigatureSet[] set = LigatureSets[i];
  1725. for (int j = 0; j < set.Length; j++)
  1726. {
  1727. ushort[] key = new ushort[set[j].Components.Length + 1];
  1728. key[0] = glyphs[i];
  1729. for (int k = 0; k < set[j].Components.Length; k++)
  1730. key[k + 1] = set[j].Components[k];
  1731. yield return new KeyValuePair<ushort[], ushort[]>(
  1732. key,
  1733. new ushort[] { set[j].LigGlyph });
  1734. }
  1735. }
  1736. }
  1737. public int IsApply(ushort[] chars, int index)
  1738. {
  1739. int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
  1740. if (index2 >= 0)
  1741. {
  1742. LigatureSet[] sets = LigatureSets[index2];
  1743. foreach (LigatureSet set in sets)
  1744. {
  1745. if (chars.Length - 1 - index - set.Components.Length >= 0)
  1746. {
  1747. bool flag = true;
  1748. for (int i = 0; i < set.Components.Length; i++)
  1749. {
  1750. if (set.Components[i] != chars[index + 1 + i])
  1751. {
  1752. flag = false;
  1753. break;
  1754. }
  1755. }
  1756. if (flag)
  1757. {
  1758. LastSetIsApply = set;
  1759. return index2;
  1760. }
  1761. }
  1762. }
  1763. }
  1764. return -1;
  1765. }
  1766. }
  1767. public struct LigatureSet
  1768. {
  1769. public ushort LigGlyph;
  1770. public ushort[] Components;
  1771. public LigatureSet(ushort ligGlyph, ushort[] components)
  1772. {
  1773. this.LigGlyph = ligGlyph;
  1774. this.Components = components;
  1775. }
  1776. }
  1777. public struct Contextual1 : Substitution
  1778. {
  1779. public struct SubRule
  1780. {
  1781. public ushort[] InputSequence;
  1782. public SubstLookupRecord[] Records;
  1783. public SubRule(ushort[] inputSequence, SubstLookupRecord[] records)
  1784. {
  1785. InputSequence = inputSequence;
  1786. Records = records;
  1787. }
  1788. }
  1789. public SubRule[][] SubRuleSets;
  1790. public Coverage Coverage;
  1791. private GlyphSubstitutionClass gsub_table;
  1792. SubRule LastSubRuleIsApply;
  1793. public Contextual1(GlyphSubstitutionClass gsub_table, SubRule[][] subRuleSets, Coverage coverage)
  1794. {
  1795. this.gsub_table = gsub_table;
  1796. SubRuleSets = subRuleSets;
  1797. Coverage = coverage;
  1798. LastSubRuleIsApply = new SubRule();
  1799. }
  1800. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  1801. {
  1802. int index2 = IsApply(chars, index);
  1803. if (index2 >= 0)
  1804. {
  1805. ApplyForce(list, chars, ref index, index2);
  1806. return true;
  1807. }
  1808. return false;
  1809. }
  1810. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  1811. {
  1812. if (types != null && !ExtFor2005.Contains(types, LookupTypes.Context))
  1813. yield break;
  1814. ushort[] glyphs = Coverage.GetGlyphs();
  1815. for (int i = 0; i < glyphs.Length; i++)
  1816. {
  1817. SubRule[] set = SubRuleSets[i];
  1818. for (int j = 0; j < set.Length; j++)
  1819. {
  1820. ushort[] key = new ushort[set[j].InputSequence.Length + 1];
  1821. key[0] = glyphs[i];
  1822. for (int k = 0; k < set[j].InputSequence.Length; k++)
  1823. key[k + 1] = set[j].InputSequence[k];
  1824. yield return new KeyValuePair<ushort[], ushort[]>(
  1825. key,
  1826. gsub_table.ApplySubstLookupRecord(key, set[j].Records));
  1827. }
  1828. }
  1829. }
  1830. public int IsApply(ushort[] chars, int index)
  1831. {
  1832. int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
  1833. if (index2 >= 0)
  1834. {
  1835. SubRule[] subRules = SubRuleSets[index2];
  1836. foreach (SubRule rule in subRules)
  1837. {
  1838. if (chars.Length - 1 - index - rule.InputSequence.Length >= 0)
  1839. {
  1840. bool flag = true;
  1841. for (int i = 0; i < rule.InputSequence.Length; i++)
  1842. {
  1843. if (rule.InputSequence[i] != chars[index + 1 + i])
  1844. {
  1845. flag = false;
  1846. break;
  1847. }
  1848. }
  1849. if (flag)
  1850. {
  1851. LastSubRuleIsApply = rule;
  1852. return index2;
  1853. }
  1854. }
  1855. }
  1856. }
  1857. return -1;
  1858. }
  1859. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  1860. {
  1861. ushort[] resultArr = new ushort[LastSubRuleIsApply.InputSequence.Length + 1];
  1862. for (int j = 0; j < resultArr.Length; j++)
  1863. {
  1864. resultArr[j] = chars[j + index];
  1865. }
  1866. list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, LastSubRuleIsApply.Records));
  1867. index += LastSubRuleIsApply.InputSequence.Length;
  1868. }
  1869. }
  1870. public struct Contextual2 : Substitution
  1871. {
  1872. public struct SubClassRule
  1873. {
  1874. public ushort[] InputSequence;
  1875. public SubstLookupRecord[] Records;
  1876. public SubClassRule(ushort[] inputSequence, SubstLookupRecord[] records)
  1877. {
  1878. InputSequence = inputSequence;
  1879. Records = records;
  1880. }
  1881. }
  1882. public SubClassRule[][] SubClassRuleSets;
  1883. private GlyphSubstitutionClass gsub_table;
  1884. public Coverage Coverage;
  1885. public ClassDefinition ClassDefinition;
  1886. SubClassRule LastSubClassRule;
  1887. public Contextual2(GlyphSubstitutionClass gsub_table, SubClassRule[][] subClassRuleSets, Coverage coverage, ClassDefinition classDefinition)
  1888. {
  1889. this.gsub_table = gsub_table;
  1890. SubClassRuleSets = subClassRuleSets;
  1891. Coverage = coverage;
  1892. ClassDefinition = classDefinition;
  1893. LastSubClassRule = new SubClassRule();
  1894. }
  1895. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  1896. {
  1897. int index2 = IsApply(chars, index);
  1898. if (index2 >= 0)
  1899. {
  1900. ApplyForce(list, chars, ref index, index2);
  1901. return true;
  1902. }
  1903. return false;
  1904. }
  1905. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  1906. {
  1907. if (types != null && !ExtFor2005.Contains(types, LookupTypes.Context))
  1908. yield break;
  1909. ushort[] glyphs = Coverage.GetGlyphs();
  1910. for (int i = 0; i < glyphs.Length; i++)
  1911. {
  1912. SubClassRule[] set = SubClassRuleSets[i];
  1913. if (set != null)
  1914. for (int j = 0; j < set.Length; j++)
  1915. {
  1916. ushort[] key = new ushort[set[j].InputSequence.Length + 1];
  1917. key[0] = glyphs[i];
  1918. for (int k = 0; k < set[j].InputSequence.Length; k++)
  1919. key[k + 1] = ClassDefinition.GetFirstGlyphByClassValue(set[j].InputSequence[k]);
  1920. yield return new KeyValuePair<ushort[], ushort[]>(
  1921. key,
  1922. gsub_table.ApplySubstLookupRecord(key, set[j].Records));
  1923. }
  1924. }
  1925. }
  1926. public int IsApply(ushort[] chars, int index)
  1927. {
  1928. int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
  1929. if (index2 >= 0)
  1930. {
  1931. SubClassRule[] subClassRules = SubClassRuleSets[index2];
  1932. if (subClassRules != null)
  1933. foreach (SubClassRule rule in subClassRules)
  1934. {
  1935. if (chars.Length - 1 - index - rule.InputSequence.Length >= 0)
  1936. {
  1937. bool flag = true;
  1938. for (int i = 0; i < rule.InputSequence.Length; i++)
  1939. {
  1940. if (rule.InputSequence[i] != ClassDefinition.GetClassValue(chars[index + 1 + i]))
  1941. {
  1942. flag = false;
  1943. break;
  1944. }
  1945. }
  1946. if (flag)
  1947. {
  1948. LastSubClassRule = rule;
  1949. return index2;
  1950. }
  1951. }
  1952. }
  1953. }
  1954. return -1;
  1955. }
  1956. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  1957. {
  1958. ushort[] resultArr = new ushort[LastSubClassRule.InputSequence.Length + 1];
  1959. for (int j = 0; j < resultArr.Length; j++)
  1960. {
  1961. resultArr[j] = chars[j + index];
  1962. }
  1963. list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, LastSubClassRule.Records));
  1964. index += LastSubClassRule.InputSequence.Length;
  1965. }
  1966. }
  1967. public struct Contextual3 : Substitution
  1968. {
  1969. public SubstLookupRecord[] Records;
  1970. public Coverage[] Coverages;
  1971. private GlyphSubstitutionClass gsub_table;
  1972. public Contextual3(GlyphSubstitutionClass gsub_table, SubstLookupRecord[] records, Coverage[] coverages)
  1973. {
  1974. this.gsub_table = gsub_table;
  1975. Records = records;
  1976. Coverages = coverages;
  1977. }
  1978. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  1979. {
  1980. int index2 = IsApply(chars, index);
  1981. if (index2 >= 0)
  1982. {
  1983. ApplyForce(list, chars, ref index, index2);
  1984. return true;
  1985. }
  1986. return false;
  1987. }
  1988. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  1989. {
  1990. ushort[] resultArr = new ushort[Coverages.Length];
  1991. for (int j = 0; j < resultArr.Length; j++)
  1992. {
  1993. resultArr[j] = chars[j + index];
  1994. }
  1995. list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, Records));
  1996. index += Coverages.Length - 1;
  1997. }
  1998. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  1999. {
  2000. if (types != null && !ExtFor2005.Contains(types, LookupTypes.Context))
  2001. yield break;
  2002. if (Coverages.Length > 0)
  2003. {
  2004. ushort[] glyphs = Coverages[0].GetGlyphs();
  2005. for (int i = 0; i < glyphs.Length; i++)
  2006. {
  2007. ushort[] key = new ushort[Coverages.Length];
  2008. key[0] = glyphs[i];
  2009. for (int k = 1; k < Coverages.Length; k++)
  2010. key[k] = Coverages[k].GetFirstGlyph();
  2011. yield return new KeyValuePair<ushort[], ushort[]>(
  2012. key,
  2013. gsub_table.ApplySubstLookupRecord(key, Records));
  2014. }
  2015. }
  2016. }
  2017. public int IsApply(ushort[] chars, int index)
  2018. {
  2019. if (Coverages.Length > 0)
  2020. {
  2021. int index2 = Coverages[0].IsSubstituteGetIndex(chars[index]);
  2022. if (index2 >= 0)
  2023. {
  2024. if (chars.Length - index - Coverages.Length >= 0)
  2025. {
  2026. bool flag = true;
  2027. for (int i = 1; i < Coverages.Length; i++)
  2028. {
  2029. if (Coverages[i].IsSubstituteGetIndex(chars[index + i]) < 0)
  2030. {
  2031. flag = false;
  2032. break;
  2033. }
  2034. }
  2035. if (flag)
  2036. {
  2037. return index;
  2038. }
  2039. }
  2040. }
  2041. }
  2042. return -1;
  2043. }
  2044. }
  2045. public struct ChainingContextual1 : Substitution
  2046. {
  2047. public struct ChainSubRule
  2048. {
  2049. public ushort[] BacktrackSequence;
  2050. public ushort[] InputSequence; // count -= 1;
  2051. public ushort[] LookAheadSequence;
  2052. public SubstLookupRecord[] Records;
  2053. public ChainSubRule(ushort[] backtrackSequence, ushort[] inputSequence, ushort[] lookAheadSequence, SubstLookupRecord[] records)
  2054. {
  2055. BacktrackSequence = backtrackSequence;
  2056. InputSequence = inputSequence;
  2057. LookAheadSequence = lookAheadSequence;
  2058. Records = records;
  2059. }
  2060. }
  2061. public GlyphSubstitutionClass gsub_table;
  2062. public ChainSubRule[][] ChainSubRuleSets;
  2063. public Coverage Coverage;
  2064. ChainSubRule LastChainSubRule;
  2065. public ChainingContextual1(GlyphSubstitutionClass gsub_table, Coverage coverage, ChainSubRule[][] chainSubRuleSets)
  2066. {
  2067. this.gsub_table = gsub_table;
  2068. ChainSubRuleSets = chainSubRuleSets;
  2069. Coverage = coverage;
  2070. LastChainSubRule = new ChainSubRule();
  2071. }
  2072. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  2073. {
  2074. int index2 = IsApply(chars, index);
  2075. if (index2 >= 0)
  2076. {
  2077. ApplyForce(list, chars, ref index, index2);
  2078. return true;
  2079. }
  2080. return false;
  2081. }
  2082. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  2083. {
  2084. if (types != null && !ExtFor2005.Contains(types, LookupTypes.ChainingContext))
  2085. yield break;
  2086. ushort[] glyphs = Coverage.GetGlyphs();
  2087. for (int i = 0; i < glyphs.Length; i++)
  2088. {
  2089. ChainSubRule[] set = ChainSubRuleSets[i];
  2090. for (int j = 0; j < set.Length; j++)
  2091. {
  2092. ushort[] key = new ushort[set[j].InputSequence.Length + 1];
  2093. key[0] = glyphs[i];
  2094. for (int k = 0; k < set[j].InputSequence.Length; k++)
  2095. key[k + 1] = set[j].InputSequence[k];
  2096. yield return new KeyValuePair<ushort[], ushort[]>(
  2097. key,
  2098. gsub_table.ApplySubstLookupRecord(key, set[j].Records));
  2099. }
  2100. }
  2101. }
  2102. public int IsApply(ushort[] chars, int index)
  2103. {
  2104. int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
  2105. if (index2 >= 0)
  2106. {
  2107. ChainSubRule[] subRules = ChainSubRuleSets[index2];
  2108. foreach (ChainSubRule rule in subRules)
  2109. {
  2110. if (chars.Length - 1 - index - rule.InputSequence.Length >= 0 &&
  2111. chars.Length - 1 - index - rule.LookAheadSequence.Length - rule.InputSequence.Length >= 0 &&
  2112. index >= rule.BacktrackSequence.Length)
  2113. {
  2114. bool flag = true;
  2115. for (int i = 0; i < rule.InputSequence.Length; i++)
  2116. {
  2117. if (rule.InputSequence[i] != chars[index + 1 + i])
  2118. {
  2119. flag = false;
  2120. break;
  2121. }
  2122. }
  2123. if (flag)
  2124. for (int i = 0; i < rule.BacktrackSequence.Length; i++)
  2125. {
  2126. if (rule.BacktrackSequence[i] != chars[index - i - 1])
  2127. {
  2128. flag = false;
  2129. break;
  2130. }
  2131. }
  2132. if (flag)
  2133. for (int i = 0; i < rule.LookAheadSequence.Length; i++)
  2134. {
  2135. if (rule.LookAheadSequence[i] != chars[index + i + 1 + rule.InputSequence.Length])
  2136. {
  2137. flag = false;
  2138. break;
  2139. }
  2140. }
  2141. if (flag)
  2142. {
  2143. LastChainSubRule = rule;
  2144. return index2;
  2145. }
  2146. }
  2147. }
  2148. }
  2149. return -1;
  2150. }
  2151. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  2152. {
  2153. ushort[] resultArr = new ushort[LastChainSubRule.InputSequence.Length + 1];
  2154. for (int j = 0; j < resultArr.Length; j++)
  2155. {
  2156. resultArr[j] = chars[j + index];
  2157. }
  2158. list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, LastChainSubRule.Records));
  2159. index += LastChainSubRule.InputSequence.Length;
  2160. }
  2161. }
  2162. public struct ChainingContextual2 : Substitution
  2163. {
  2164. public struct ChainSubClassRule
  2165. {
  2166. public ushort[] BacktrackSequence;
  2167. public ushort[] InputSequence; // count -= 1;
  2168. public ushort[] LookAheadSequence;
  2169. public SubstLookupRecord[] Records;
  2170. public ChainSubClassRule(ushort[] backtrackSequence, ushort[] inputSequence, ushort[] lookAheadSequence, SubstLookupRecord[] records)
  2171. {
  2172. BacktrackSequence = backtrackSequence;
  2173. InputSequence = inputSequence;
  2174. LookAheadSequence = lookAheadSequence;
  2175. Records = records;
  2176. }
  2177. }
  2178. public ChainSubClassRule[][] SubClassRuleSets;
  2179. private GlyphSubstitutionClass gsub_table;
  2180. public Coverage Coverage;
  2181. public ClassDefinition BacktrackClassDefinition;
  2182. public ClassDefinition InputClassDefinition;
  2183. public ClassDefinition LookaheadClassDefinition;
  2184. ChainSubClassRule LastChainSubClassRule;
  2185. public ChainingContextual2(
  2186. GlyphSubstitutionClass gsub_table,
  2187. ChainSubClassRule[][] subClassRuleSets,
  2188. Coverage coverage,
  2189. ClassDefinition backtrackClassDefinition,
  2190. ClassDefinition inputClassDefinition,
  2191. ClassDefinition lookaheadClassDefinition)
  2192. {
  2193. this.gsub_table = gsub_table;
  2194. SubClassRuleSets = subClassRuleSets;
  2195. Coverage = coverage;
  2196. BacktrackClassDefinition = backtrackClassDefinition;
  2197. InputClassDefinition = inputClassDefinition;
  2198. LookaheadClassDefinition = lookaheadClassDefinition;
  2199. LastChainSubClassRule = new ChainSubClassRule();
  2200. }
  2201. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  2202. {
  2203. int index2 = IsApply(chars, index);
  2204. if (index2 >= 0)
  2205. {
  2206. ApplyForce(list, chars, ref index, index2);
  2207. return true;
  2208. }
  2209. return false;
  2210. }
  2211. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  2212. {
  2213. if (types != null && !ExtFor2005.Contains(types, LookupTypes.ChainingContext))
  2214. yield break;
  2215. ushort[] glyphs = Coverage.GetGlyphs();
  2216. for (int i = 0; i < glyphs.Length; i++)
  2217. {
  2218. ChainSubClassRule[] set = SubClassRuleSets[i];
  2219. if (set != null)
  2220. for (int j = 0; j < set.Length; j++)
  2221. {
  2222. ushort[] key = new ushort[set[j].InputSequence.Length + 1];
  2223. key[0] = glyphs[i];
  2224. for (int k = 0; k < set[j].InputSequence.Length; k++)
  2225. key[k + 1] = InputClassDefinition.GetFirstGlyphByClassValue(set[j].InputSequence[k]);
  2226. yield return new KeyValuePair<ushort[], ushort[]>(
  2227. key,
  2228. gsub_table.ApplySubstLookupRecord(key, set[j].Records));
  2229. }
  2230. }
  2231. }
  2232. public int IsApply(ushort[] chars, int index)
  2233. {
  2234. int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
  2235. if (index2 >= 0)
  2236. {
  2237. ChainSubClassRule[] subClassRules = SubClassRuleSets[index2];
  2238. if (subClassRules != null)
  2239. foreach (ChainSubClassRule rule in subClassRules)
  2240. {
  2241. if (chars.Length - 1 - index - rule.InputSequence.Length >= 0 &&
  2242. chars.Length - 1 - index - rule.LookAheadSequence.Length - rule.InputSequence.Length >= 0 &&
  2243. index >= rule.BacktrackSequence.Length)
  2244. {
  2245. bool flag = true;
  2246. for (int i = 0; i < rule.InputSequence.Length; i++)
  2247. {
  2248. if (rule.InputSequence[i] != InputClassDefinition.GetClassValue(chars[index + 1 + i]))
  2249. {
  2250. flag = false;
  2251. break;
  2252. }
  2253. }
  2254. if (flag)
  2255. for (int i = 0; i < rule.BacktrackSequence.Length; i++)
  2256. {
  2257. if (rule.BacktrackSequence[i] != BacktrackClassDefinition.GetClassValue(chars[index - i - 1]))
  2258. {
  2259. flag = false;
  2260. break;
  2261. }
  2262. }
  2263. if (flag)
  2264. for (int i = 0; i < rule.LookAheadSequence.Length; i++)
  2265. {
  2266. if (rule.LookAheadSequence[i] !=
  2267. LookaheadClassDefinition.GetClassValue(
  2268. chars[index + i + 1 + rule.InputSequence.Length]))
  2269. {
  2270. flag = false;
  2271. break;
  2272. }
  2273. }
  2274. if (flag)
  2275. {
  2276. LastChainSubClassRule = rule;
  2277. return index2;
  2278. }
  2279. }
  2280. }
  2281. }
  2282. return -1;
  2283. }
  2284. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  2285. {
  2286. ushort[] resultArr = new ushort[LastChainSubClassRule.InputSequence.Length + 1];
  2287. for (int j = 0; j < resultArr.Length; j++)
  2288. {
  2289. resultArr[j] = chars[j + index];
  2290. }
  2291. list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, LastChainSubClassRule.Records));
  2292. index += LastChainSubClassRule.InputSequence.Length;
  2293. }
  2294. }
  2295. public struct ChainingContextual3 : Substitution
  2296. {
  2297. public SubstLookupRecord[] Records;
  2298. public Coverage[] BacktrackCoverages;
  2299. public Coverage[] InputCoverages;
  2300. public Coverage[] LookaheadCoverages;
  2301. private GlyphSubstitutionClass gsub_table;
  2302. public ChainingContextual3(GlyphSubstitutionClass gsub_table, SubstLookupRecord[] records, Coverage[] backtrackCoverages, Coverage[] inputCoverages, Coverage[] lookaheadCoverages)
  2303. {
  2304. this.gsub_table = gsub_table;
  2305. Records = records;
  2306. BacktrackCoverages = backtrackCoverages;
  2307. InputCoverages = inputCoverages;
  2308. LookaheadCoverages = lookaheadCoverages;
  2309. }
  2310. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  2311. {
  2312. int index2 = IsApply(chars, index);
  2313. if (index2 >= 0)
  2314. {
  2315. ApplyForce(list, chars, ref index, index2);
  2316. return true;
  2317. }
  2318. return false;
  2319. }
  2320. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  2321. {
  2322. ushort[] resultArr = new ushort[InputCoverages.Length];
  2323. for (int j = 0; j < resultArr.Length; j++)
  2324. {
  2325. resultArr[j] = chars[j + index];
  2326. }
  2327. list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, Records));
  2328. index += InputCoverages.Length - 1;
  2329. }
  2330. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  2331. {
  2332. if (types != null && !ExtFor2005.Contains(types, LookupTypes.ChainingContext))
  2333. yield break;
  2334. if (InputCoverages.Length > 0)
  2335. {
  2336. ushort[] glyphs = InputCoverages[0].GetGlyphs();
  2337. for (int i = 0; i < glyphs.Length; i++)
  2338. {
  2339. ushort[] key = new ushort[InputCoverages.Length];
  2340. key[0] = glyphs[i];
  2341. if (InputCoverages.Length > 0)
  2342. for (int k = 1; k < InputCoverages.Length; k++)
  2343. key[k] = InputCoverages[k].GetFirstGlyph();
  2344. yield return new KeyValuePair<ushort[], ushort[]>(
  2345. key,
  2346. gsub_table.ApplySubstLookupRecord(key, Records));
  2347. }
  2348. }
  2349. }
  2350. public int IsApply(ushort[] chars, int index)
  2351. {
  2352. if (InputCoverages.Length > 0)
  2353. {
  2354. int index2 = InputCoverages[0].IsSubstituteGetIndex(chars[index]);
  2355. if (index2 >= 0)
  2356. {
  2357. if (chars.Length - 1 - index - InputCoverages.Length >= 0 &&
  2358. chars.Length - 1 - index - LookaheadCoverages.Length - InputCoverages.Length >= 0 &&
  2359. index >= BacktrackCoverages.Length)
  2360. {
  2361. bool flag = true;
  2362. for (int i = 1; i < InputCoverages.Length; i++)
  2363. {
  2364. if (InputCoverages[i].IsSubstituteGetIndex(chars[index + i]) < 0)
  2365. {
  2366. flag = false;
  2367. break;
  2368. }
  2369. }
  2370. if (flag)
  2371. for (int i = 0; i < BacktrackCoverages.Length; i++)
  2372. {
  2373. if (BacktrackCoverages[i].IsSubstituteGetIndex(chars[index - i - 1]) < 0)
  2374. {
  2375. flag = false;
  2376. break;
  2377. }
  2378. }
  2379. if (flag)
  2380. for (int i = 0; i < LookaheadCoverages.Length; i++)
  2381. {
  2382. if (LookaheadCoverages[i].IsSubstituteGetIndex(
  2383. chars[index + i + 1 + InputCoverages.Length]) < 0)
  2384. {
  2385. flag = false;
  2386. break;
  2387. }
  2388. }
  2389. if (flag)
  2390. {
  2391. return index2;
  2392. }
  2393. }
  2394. }
  2395. }
  2396. return -1;
  2397. }
  2398. }
  2399. public struct Extension : Substitution
  2400. {
  2401. public Substitution Substitution;
  2402. public ushort LookupType;
  2403. public ushort Format;
  2404. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  2405. {
  2406. return Substitution.Apply(list, chars, ref index);
  2407. }
  2408. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  2409. {
  2410. Substitution.ApplyForce(list, chars, ref index, coverageIndex);
  2411. }
  2412. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  2413. {
  2414. if (types != null && !ExtFor2005.Contains(types, LookupTypes.ExtensionSubstitution))
  2415. return new KeyValuePair<ushort[], ushort[]>[0];
  2416. return Substitution.GetList(types);
  2417. }
  2418. public int IsApply(ushort[] chars, int index)
  2419. {
  2420. return Substitution.IsApply(chars, index);
  2421. }
  2422. }
  2423. public struct VoidSubstitution : Substitution
  2424. {
  2425. public bool Apply(List<ushort> list, ushort[] chars, ref int index)
  2426. {
  2427. return false;
  2428. }
  2429. public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
  2430. {
  2431. }
  2432. public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
  2433. {
  2434. yield break;
  2435. }
  2436. public int IsApply(ushort[] chars, int index)
  2437. {
  2438. return -1;
  2439. }
  2440. }
  2441. internal IEnumerable<KeyValuePair<ushort[], ushort[]>> GetSubstitutions(string script, string language, string feature, LookupTypes[] types)
  2442. {
  2443. if (script_list.ContainsKey(script))
  2444. {
  2445. Hashtable lang_sys_hash = script_list[script] as Hashtable;
  2446. Hashtable lang_sys = null;
  2447. if (lang_sys_hash.ContainsKey(language))
  2448. {
  2449. lang_sys = lang_sys_hash[language] as Hashtable;
  2450. }
  2451. else if (lang_sys_hash.ContainsKey(string.Empty))
  2452. {
  2453. lang_sys = lang_sys_hash[string.Empty] as Hashtable;
  2454. }
  2455. if (lang_sys != null)
  2456. {
  2457. if (lang_sys.ContainsKey(feature))
  2458. {
  2459. foreach (ushort offset in (ushort[])lang_sys[feature])
  2460. {
  2461. LookupEntry le = (LookupEntry)lookup_list[offset];
  2462. for (int i = 0; i < le.subs.Length; i++)
  2463. {
  2464. foreach (KeyValuePair<ushort[], ushort[]> sub in le.subs[i].GetList(types))
  2465. yield return sub;
  2466. }
  2467. }
  2468. }
  2469. }
  2470. }
  2471. }
  2472. public struct VoidCoverage : Coverage
  2473. {
  2474. public ushort GetFirstGlyph()
  2475. {
  2476. return 1;
  2477. }
  2478. public ushort[] GetGlyphs()
  2479. {
  2480. return new ushort[0];
  2481. }
  2482. public int IsSubstituteGetIndex(ushort ch)
  2483. {
  2484. return -1;
  2485. }
  2486. }
  2487. public interface ClassDefinition
  2488. {
  2489. ushort GetClassValue(ushort glyph);
  2490. ushort GetFirstGlyphByClassValue(ushort v);
  2491. }
  2492. public struct ClassDefinition1 : ClassDefinition
  2493. {
  2494. ushort StartGlyphId;
  2495. ushort[] ClassValues;
  2496. public ClassDefinition1(ushort startGlyphId, ushort[] classValues)
  2497. {
  2498. StartGlyphId = startGlyphId;
  2499. ClassValues = classValues;
  2500. }
  2501. public ushort GetClassValue(ushort glyph)
  2502. {
  2503. int index = glyph - StartGlyphId;
  2504. if (index >= 0 && index < ClassValues.Length)
  2505. return ClassValues[index];
  2506. return 0;
  2507. }
  2508. public ushort GetFirstGlyphByClassValue(ushort v)
  2509. {
  2510. for (int i = 0; i < ClassValues.Length; i++)
  2511. if (ClassValues[i] == v)
  2512. return (ushort)(StartGlyphId + i);
  2513. return StartGlyphId;
  2514. }
  2515. }
  2516. public struct ClassDefinition2 : ClassDefinition
  2517. {
  2518. ClassRangeRecord[] Records;
  2519. public ClassDefinition2(ClassRangeRecord[] records)
  2520. {
  2521. Records = records;
  2522. }
  2523. public ushort GetClassValue(ushort glyph)
  2524. {
  2525. foreach (ClassRangeRecord record in Records)
  2526. if (record.StartGlyphID <= glyph && record.EndGlyphID >= glyph)
  2527. return record.ClassValue;
  2528. return 0;
  2529. }
  2530. public ushort GetFirstGlyphByClassValue(ushort v)
  2531. {
  2532. foreach (ClassRangeRecord record in Records)
  2533. if (record.ClassValue == v)
  2534. return record.StartGlyphID;
  2535. if (Records.Length > 0)
  2536. return Records[0].StartGlyphID;
  2537. return 0;
  2538. }
  2539. }
  2540. public struct VoidClassDefinition : ClassDefinition
  2541. {
  2542. public ushort GetClassValue(ushort glyph)
  2543. {
  2544. return 0;
  2545. }
  2546. public ushort GetFirstGlyphByClassValue(ushort v)
  2547. {
  2548. //TODO
  2549. //TO DO
  2550. // WHAT TO DO??? just return zero value, let it be space plz :)
  2551. return 1;
  2552. }
  2553. }
  2554. }
  2555. }
  2556. #pragma warning restore