12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Runtime.InteropServices;
- using FastReport.Fonts.LinqExts;
- #pragma warning disable CS3001, CS3002, CS3003, CS1591 // Missing XML comment for publicly visible type or member
- namespace FastReport.Fonts
- {
- /// <summary>
- /// GlyphSubstitution table
- /// </summary>
- public class GlyphSubstitutionClass : TrueTypeTable
- {
- #region "Structure definition"
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct GSUB_Header
- {
- [FieldOffset(0)]
- public uint Version; // Version of the GSUB table-initially set to 0x00010000
- [FieldOffset(4)]
- public ushort ScriptList; // Offset to ScriptList table-from beginning of GSUB table
- [FieldOffset(6)]
- public ushort FeatureList; // Offset to FeatureList table-from beginning of GSUB table
- [FieldOffset(8)]
- public ushort LookupList; // Offset to LookupList table-from beginning of GSUB table
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct ScriptListTable
- {
- [FieldOffset(0)]
- public ushort CountScripts; // Count of ScriptListRecord
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct ScriptListRecord
- {
- [FieldOffset(0)]
- public uint ScriptTag; // 4-byte ScriptTag identifier
- [FieldOffset(4)]
- public ushort ScriptOffset; // Offset to Script table-from beginning of ScriptList
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct ScriptTable
- {
- [FieldOffset(0)]
- public ushort DefaultLangSys; // Offset to DefaultLangSys table-from beginning of Script table-may be NULL
- [FieldOffset(2)]
- public ushort LangSysCount; // Number of LangSysRecords for this script-excluding the DefaultLangSys
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct LangSysRecord
- {
- [FieldOffset(0)]
- public uint LangSysTag; // 4-byte LangSysTag identifier
- [FieldOffset(4)]
- public ushort LangSys; // Offset to LangSys table-from beginning of Script table
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct LangSysTable
- {
- [FieldOffset(0)]
- public ushort LookupOrder; // = NULL (reserved for an offset to a reordering table)
- [FieldOffset(2)]
- public ushort ReqFeatureIndex; // Index of a feature required for this language system- if no required features = 0xFFFF
- [FieldOffset(4)]
- public ushort FeatureCount; // Number of FeatureIndex values for this language system-excludes the required feature
- }
- // Related to feature table
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct FeaturesListTable
- {
- [FieldOffset(0)]
- public ushort CountFeatures; // Count of FeaturesListRecord
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct FeatureRecord
- {
- [FieldOffset(0)]
- public uint FeatureTag; // 4-byte feature identification tag
- [FieldOffset(4)]
- public ushort Feature; // Offset to Feature table-from beginning of FeatureList
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct FeatureTable
- {
- [FieldOffset(0)]
- public ushort FeatureParams;
- [FieldOffset(2)]
- public ushort LookupCount;
- }
- #endregion
- private GSUB_Header header;
- private IntPtr gsub_ptr;
- private Hashtable script_list = new Hashtable();
- private LookupEntry[] lookup_list;
- public IEnumerable<string> Scripts
- {
- get
- {
- foreach (string script_str in script_list.Keys)
- yield return script_str;
- }
- }
- private ushort[] LoadFeature(uint feature_idx, out string FeatureTag)
- {
- IntPtr feature_list_table_ptr = Increment(gsub_ptr, (int)header.FeatureList);
- ushort feature_count = SwapUInt16((ushort)Marshal.PtrToStructure(feature_list_table_ptr, typeof(ushort)));
- if (feature_idx >= feature_count) throw new Exception("Feature index out of bound");
- IntPtr feature_record_ptr = Increment(feature_list_table_ptr, (int)(sizeof(ushort) + feature_idx * 6));
- FeatureRecord feature_record = (FeatureRecord)Marshal.PtrToStructure(feature_record_ptr, typeof(FeatureRecord));
- feature_record.Feature = SwapUInt16(feature_record.Feature);
- FeatureTag = "" +
- (char)(0xff & feature_record.FeatureTag) +
- (char)(0xff & (feature_record.FeatureTag >> 8)) +
- (char)(0xff & (feature_record.FeatureTag >> 16)) +
- (char)(0xff & (feature_record.FeatureTag >> 24));
- IntPtr feature_table_ptr = Increment(feature_list_table_ptr, feature_record.Feature);
- FeatureTable feature_table = (FeatureTable)Marshal.PtrToStructure(feature_table_ptr, typeof(FeatureTable));
- feature_table.LookupCount = SwapUInt16(feature_table.LookupCount);
- ushort[] OffsetLookupList = new ushort[feature_table.LookupCount];
- IntPtr lookup_list_ptr = Increment(feature_table_ptr, Marshal.SizeOf(feature_table));
- for (int i = 0; i < feature_table.LookupCount; i++)
- {
- ushort lookuip_index = SwapUInt16((ushort)Marshal.PtrToStructure(lookup_list_ptr, typeof(ushort)));
- OffsetLookupList[i] = lookuip_index;
- if (lookuip_index == 30)
- {
- //to do remove
- }
- lookup_list_ptr = Increment(lookup_list_ptr, sizeof(ushort));
- }
- return OffsetLookupList;
- }
- internal IEnumerable<string> GetFeatures(string script, string language)
- {
- if (script_list.ContainsKey(script))
- if ((script_list[script] as Hashtable).ContainsKey(language))
- {
- foreach (string feature_str in ((script_list[script] as Hashtable)[language] as Hashtable).Keys)
- yield return feature_str;
- }
- }
- internal IEnumerable<string> Languages(string script)
- {
- if (script_list.ContainsKey(script))
- {
- foreach (string lang_str in (script_list[script] as Hashtable).Keys)
- yield return lang_str;
- }
- }
- private Hashtable LoadLanguageSystemTable(IntPtr lang_sys_rec_ptr)
- {
- Hashtable Features = new Hashtable();
- LangSysTable lang_sys_table = (LangSysTable)Marshal.PtrToStructure(lang_sys_rec_ptr, typeof(LangSysTable));
- lang_sys_table.LookupOrder = SwapUInt16(lang_sys_table.LookupOrder);
- lang_sys_table.ReqFeatureIndex = SwapUInt16(lang_sys_table.ReqFeatureIndex);
- lang_sys_table.FeatureCount = SwapUInt16(lang_sys_table.FeatureCount);
- IntPtr feature_index_ptr = Increment(lang_sys_rec_ptr, Marshal.SizeOf(lang_sys_table));
- ushort[] feature_indexes = new ushort[lang_sys_table.FeatureCount];
- for (int k = 0; k < lang_sys_table.FeatureCount; k++)
- {
- feature_indexes[k] = SwapUInt16((ushort)Marshal.PtrToStructure(feature_index_ptr, typeof(ushort)));
- string FeatureTag;
- ushort[] LookupOffsets = LoadFeature(feature_indexes[k], out FeatureTag);
- #if DEBUG_TTF
- Console.WriteLine("\t\t[" + k + "]: " + FeatureTag + " of " + LookupOffsets.Length);
- #endif
- if (!Features.ContainsKey(FeatureTag))
- Features.Add(FeatureTag, LookupOffsets);
- #if DEBUG_TTF
- else
- Console.WriteLine("Duplicated record " + FeatureTag);
- #endif
- feature_index_ptr = Increment(feature_index_ptr, sizeof(ushort));
- }
- return Features;
- }
- private void LoadScriptList()
- {
- IntPtr script_list_table_ptr = Increment(gsub_ptr, (int)header.ScriptList);
- ScriptListTable script_list_table = (ScriptListTable)Marshal.PtrToStructure(script_list_table_ptr, typeof(ScriptListTable));
- script_list_table.CountScripts = SwapUInt16(script_list_table.CountScripts);
- IntPtr script_record_ptr = Increment(script_list_table_ptr, Marshal.SizeOf(script_list_table));
- for (int i = 0; i < script_list_table.CountScripts; i++)
- {
- ScriptListRecord script_record = (ScriptListRecord)Marshal.PtrToStructure(script_record_ptr, typeof(ScriptListRecord));
- script_record.ScriptOffset = SwapUInt16(script_record.ScriptOffset);
- string ScriptTag = "" +
- (char)(0xff & script_record.ScriptTag) +
- (char)(0xff & (script_record.ScriptTag >> 8)) +
- (char)(0xff & (script_record.ScriptTag >> 16)) +
- (char)(0xff & (script_record.ScriptTag >> 24));
- #if DEBUG_TTF
- Console.WriteLine("[" + ScriptTag + "]");
- #endif
- Hashtable lang_sys_hash = new Hashtable();
- script_list.Add(ScriptTag, lang_sys_hash);
- IntPtr script_table_ptr = Increment(script_list_table_ptr, script_record.ScriptOffset);
- ScriptTable script_table = (ScriptTable)Marshal.PtrToStructure(script_table_ptr, typeof(ScriptTable));
- script_table.DefaultLangSys = SwapUInt16(script_table.DefaultLangSys);
- script_table.LangSysCount = SwapUInt16(script_table.LangSysCount);
- IntPtr lang_sys_rec_ptr;
- if (script_table.DefaultLangSys != 0)
- {
- lang_sys_rec_ptr = Increment(script_table_ptr, script_table.DefaultLangSys);
- #if DEBUG_TTF
- Console.WriteLine("\t\"!DEF\"");
- #endif
- lang_sys_hash.Add("", LoadLanguageSystemTable(lang_sys_rec_ptr));
- }
- lang_sys_rec_ptr = Increment(script_table_ptr, Marshal.SizeOf(script_table));
- for (int j = 0; j < script_table.LangSysCount; j++)
- {
- LangSysRecord lang_sys_rec = (LangSysRecord)Marshal.PtrToStructure(lang_sys_rec_ptr, typeof(LangSysRecord));
- lang_sys_rec.LangSys = SwapUInt16(lang_sys_rec.LangSys);
- string LangSysTag = "" +
- (char)(0xff & lang_sys_rec.LangSysTag) +
- (char)(0xff & (lang_sys_rec.LangSysTag >> 8)) +
- (char)(0xff & (lang_sys_rec.LangSysTag >> 16)) +
- (char)(0xff & (lang_sys_rec.LangSysTag >> 24));
- #if DEBUG_TTF
- Console.WriteLine("\t\"" + LangSysTag + "\"");
- #endif
- IntPtr lang_sys_rec_ptr_offset = Increment(script_table_ptr, lang_sys_rec.LangSys);
- lang_sys_hash.Add(LangSysTag, LoadLanguageSystemTable(lang_sys_rec_ptr_offset));
- lang_sys_rec_ptr = Increment(lang_sys_rec_ptr, Marshal.SizeOf(lang_sys_rec));
- }
- script_record_ptr = Increment(script_record_ptr, Marshal.SizeOf(script_record));
- }
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct LookupTableRecordHeader
- {
- [FieldOffset(0)]
- public ushort LookupType; // Different enumerations for GSUB and GPOS
- [FieldOffset(2)]
- public ushort LookupFlag; // Lookup qualifiers
- [FieldOffset(4)]
- public ushort SubTableCount; // Number of SubTables for this lookup [FieldOffset(2)]
- }
- internal struct LookupEntry
- {
- public LookupTableRecordHeader record_header;
- public ushort[] subtable_offsets;
- public IntPtr[] subtable_ptrs;
- public Substitution[] subs;
- public override string ToString()
- {
- return "" + ((LookupTypes)record_header.LookupType).ToString() + " : " + record_header.LookupFlag + " [" + record_header.SubTableCount.ToString() + "]";
- }
- }
- public enum LookupTypes
- {
- Single = 1, // Replace one glyph with one glyph
- Multiple = 2, // Replace one glyph with more than one glyph
- Alternate = 3, // Replace one glyph with one of many glyphs
- Ligature = 4, // Replace multiple glyphs with one glyph
- Context = 5, // Replace one or more glyphs in context
- ChainingContext = 6, // Replace one or more glyphs in chained context
- ExtensionSubstitution = 7, // Extension mechanism for other substitutions (i.e. this excludes the Extension type substitution itself)
- ReverseChainingContextSingle = 8 // Applied in reverse order, replace single glyph in chaining context
- //9+ Reserved For future use (set to zero)
- }
- private void LoadLookupList()
- {
- IntPtr lookup_list_table_ptr = Increment(gsub_ptr, (int)header.LookupList);
- ushort LookupListCount = SwapUInt16((ushort)Marshal.PtrToStructure(lookup_list_table_ptr, typeof(ushort)));
- lookup_list = new LookupEntry[LookupListCount];
- IntPtr lookup_list_ptr = Increment(lookup_list_table_ptr, sizeof(ushort));
- for (int i = 0; i < LookupListCount; i++)
- {
- ushort lookup_index = SwapUInt16((ushort)Marshal.PtrToStructure(lookup_list_ptr, typeof(ushort)));
- lookup_list_ptr = Increment(lookup_list_ptr, sizeof(ushort));
- IntPtr lookup_list_entry_ptr = Increment(lookup_list_table_ptr, lookup_index);
- IntPtr lookup_table_ptr = lookup_list_entry_ptr;
- lookup_list[i].record_header = (LookupTableRecordHeader)Marshal.PtrToStructure(lookup_list_entry_ptr, typeof(LookupTableRecordHeader));
- lookup_list_entry_ptr = Increment(lookup_list_entry_ptr, Marshal.SizeOf(lookup_list[i].record_header));
- lookup_list[i].record_header.LookupType = SwapUInt16(lookup_list[i].record_header.LookupType);
- lookup_list[i].record_header.LookupFlag = SwapUInt16(lookup_list[i].record_header.LookupFlag);
- lookup_list[i].record_header.SubTableCount = SwapUInt16(lookup_list[i].record_header.SubTableCount);
- lookup_list[i].subtable_offsets = new ushort[lookup_list[i].record_header.SubTableCount];
- lookup_list[i].subtable_ptrs = new IntPtr[lookup_list[i].record_header.SubTableCount];
- lookup_list[i].subs = new Substitution[lookup_list[i].record_header.SubTableCount];
- for (int j = 0; j < lookup_list[i].record_header.SubTableCount; j++)
- {
- lookup_list[i].subtable_offsets[j] = SwapUInt16((ushort)Marshal.PtrToStructure(lookup_list_entry_ptr, typeof(ushort)));
- lookup_list[i].subtable_ptrs[j] = Increment(lookup_table_ptr, lookup_list[i].subtable_offsets[j]);
- lookup_list_entry_ptr = Increment(lookup_list_entry_ptr, sizeof(ushort));
- lookup_list[i].subs[j] = LoadSubstitution(lookup_list[i].record_header.LookupType, lookup_list[i].subtable_ptrs[j]);
- }
- //to do: lookup list
- }
- }
- private Substitution LoadSubstitution(ushort lookupType, IntPtr intPtr)
- {
- #if DEBUG_TTF
- Console.WriteLine("\tLookupType[" + ((LookupTypes)lookupType).ToString() + "]");
- #endif
- switch ((LookupTypes)lookupType)
- {
- case LookupTypes.Single:
- return LoadSingleSubstitution(intPtr);
- case LookupTypes.Multiple:
- return LoadMultipleSubstitution(intPtr);
- case LookupTypes.Alternate:
- break;
- case LookupTypes.Ligature:
- return LoadLigaturesSubtable(intPtr);
- //break;
- case LookupTypes.Context:
- return LoadContextSubstitution(intPtr);
- //break;
- case LookupTypes.ChainingContext:
- return LoadChainingContext(intPtr);
- //break;
- case LookupTypes.ExtensionSubstitution:
- ExtensionSubstFormat extensionSubstFormat = (ExtensionSubstFormat)
- Marshal.PtrToStructure(intPtr,
- typeof(ExtensionSubstFormat));
- extensionSubstFormat.ExtensionLookupType = SwapUInt16(extensionSubstFormat.ExtensionLookupType);
- extensionSubstFormat.SubstFormat = SwapUInt16(extensionSubstFormat.SubstFormat);
- extensionSubstFormat.ExtensionOffset = SwapUInt32(extensionSubstFormat.ExtensionOffset);
- Extension extension = new Extension();
- extension.Format = extensionSubstFormat.SubstFormat;
- extension.LookupType = extensionSubstFormat.ExtensionLookupType;
- extension.Substitution = LoadSubstitution(
- extension.LookupType,
- Increment(intPtr, extensionSubstFormat.ExtensionOffset));
- return extension;
- case LookupTypes.ReverseChainingContextSingle:
- break;
- }
- return new VoidSubstitution();
- }
- private Substitution LoadContextSubstitution(IntPtr lookup_entry)
- {
- ushort format = (ushort)Marshal.PtrToStructure(lookup_entry, typeof(ushort));
- format = SwapUInt16(format);
- switch (format)
- {
- case 1:
- ContextSubstFormat1 type1 = (ContextSubstFormat1)Marshal.PtrToStructure(lookup_entry, typeof(ContextSubstFormat1));
- type1.SubstFormat = SwapUInt16(type1.SubstFormat);
- type1.Coverage = SwapUInt16(type1.Coverage);
- type1.SubRuleSetCount = SwapUInt16(type1.SubRuleSetCount);
- IntPtr sets_offset = Increment(lookup_entry, Marshal.SizeOf(type1));
- Contextual1.SubRule[][] subRuleSets = new Contextual1.SubRule[type1.SubRuleSetCount][];
- for (int i = 0; i < type1.SubRuleSetCount; i++)
- {
- ushort offset = (ushort)Marshal.PtrToStructure(sets_offset, typeof(ushort));
- offset = SwapUInt16(offset);
- IntPtr subruleset_offset_table = Increment(lookup_entry, offset);
- ushort subRuleCount = (ushort)Marshal.PtrToStructure(subruleset_offset_table, typeof(ushort));
- subRuleCount = SwapUInt16(subRuleCount);
- IntPtr subrule_offsets = Increment(subruleset_offset_table, Marshal.SizeOf(subRuleCount));
- Contextual1.SubRule[] subRuleSet = new Contextual1.SubRule[subRuleCount];
- for (int j = 0; j < subRuleCount; j++)
- {
- ushort subRuleOffset = (ushort)Marshal.PtrToStructure(subrule_offsets, typeof(ushort));
- IntPtr subrule_table = Increment(subruleset_offset_table, subRuleOffset);
- SubRuleTable subRule = (SubRuleTable)Marshal.PtrToStructure(subrule_table, typeof(SubRuleTable));
- IntPtr subrule_table_arrays = Increment(subrule_table, Marshal.SizeOf(subRule));
- subRule.GlyphCount = SwapUInt16(subRule.GlyphCount);
- subRule.SubstitutionCount = SwapUInt16(subRule.SubstitutionCount);
- ushort[] glyphs = new ushort[subRule.GlyphCount - 1];
- for (int k = 0; k < subRule.GlyphCount - 1; k++)
- {
- ushort glyph = (ushort)Marshal.PtrToStructure(subrule_table_arrays, typeof(ushort));
- glyph = SwapUInt16(glyph);
- subrule_table_arrays = Increment(subrule_table_arrays, Marshal.SizeOf(glyph));
- glyphs[k] = glyph;
- }
- SubstLookupRecord[] records = new SubstLookupRecord[subRule.SubstitutionCount];
- for (int k = 0; k < subRule.SubstitutionCount; k++)
- {
- SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(subrule_table_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = SwapUInt16(record.LookupListIndex);
- subrule_table_arrays = Increment(subrule_table_arrays, Marshal.SizeOf(record));
- records[k] = record;
- }
- subRuleSet[j] = new Contextual1.SubRule(glyphs, records);
- subrule_offsets = Increment(subrule_offsets, Marshal.SizeOf(subRuleOffset));
- }
- subRuleSets[i] = subRuleSet;
- sets_offset = Increment(lookup_entry, Marshal.SizeOf(offset));
- }
- return new Contextual1(this, subRuleSets, LoadCoverage(Increment(lookup_entry, type1.Coverage)));
- case 2:
- ContextSubstFormat2 type2 = (ContextSubstFormat2)Marshal.PtrToStructure(lookup_entry, typeof(ContextSubstFormat2));
- type2.SubstFormat = SwapUInt16(type2.SubstFormat);
- type2.Coverage = SwapUInt16(type2.Coverage);
- type2.ClassDefOffset = SwapUInt16(type2.ClassDefOffset);
- type2.SubClassSetCount = SwapUInt16(type2.SubClassSetCount);
- Contextual2.SubClassRule[][] subClassRuleSets = new Contextual2.SubClassRule[type2.SubClassSetCount][];
- IntPtr sub_class_set_offset = Increment(lookup_entry, Marshal.SizeOf(type2));
- for (int i = 0; i < type2.SubClassSetCount; i++)
- {
- ushort offset = (ushort)Marshal.PtrToStructure(sub_class_set_offset, typeof(ushort));
- if (offset == 0)
- subClassRuleSets[i] = null;
- else
- {
- offset = SwapUInt16(offset);
- IntPtr sub_class_set_table = Increment(lookup_entry, offset);
- ushort count = (ushort)Marshal.PtrToStructure(sub_class_set_table, typeof(ushort));
- count = SwapUInt16(count);
- IntPtr sub_class_rule_offset = Increment(sub_class_set_table, Marshal.SizeOf(count));
- Contextual2.SubClassRule[] subClassSet = new Contextual2.SubClassRule[count];
- for (int j = 0; j < count; j++)
- {
- ushort offset2 = (ushort)Marshal.PtrToStructure(sub_class_rule_offset, typeof(ushort));
- offset2 = SwapUInt16(offset2);
- IntPtr sub_class_rule_table = Increment(sub_class_set_table, offset2);
- SubClassRule subClassRule = (SubClassRule)Marshal.PtrToStructure(sub_class_rule_table, typeof(SubClassRule));
- IntPtr subclassrule_table_arrays = Increment(sub_class_rule_table, Marshal.SizeOf(subClassRule));
- subClassRule.ClassCount = SwapUInt16(subClassRule.ClassCount);
- subClassRule.SubstitutionCount = SwapUInt16(subClassRule.SubstitutionCount);
- ushort[] glyphClassess = new ushort[subClassRule.ClassCount - 1];
- for (int k = 0; k < subClassRule.ClassCount - 1; k++)
- {
- ushort glyphClass = (ushort)Marshal.PtrToStructure(subclassrule_table_arrays, typeof(ushort));
- glyphClass = SwapUInt16(glyphClass);
- subclassrule_table_arrays = Increment(subclassrule_table_arrays, Marshal.SizeOf(glyphClass));
- glyphClassess[k] = glyphClass;
- }
- SubstLookupRecord[] records = new SubstLookupRecord[subClassRule.SubstitutionCount];
- for (int k = 0; k < subClassRule.SubstitutionCount; k++)
- {
- SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(subclassrule_table_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = SwapUInt16(record.LookupListIndex);
- subclassrule_table_arrays = Increment(subclassrule_table_arrays, Marshal.SizeOf(record));
- records[k] = record;
- }
- subClassSet[j] = new Contextual2.SubClassRule(glyphClassess, records);
- sub_class_rule_offset = Increment(sub_class_rule_offset, Marshal.SizeOf(offset2));
- }
- subClassRuleSets[i] = subClassSet;
- }
- sub_class_set_offset = Increment(sub_class_set_offset, Marshal.SizeOf(offset));
- }
- return new Contextual2(this, subClassRuleSets, LoadCoverage(Increment(lookup_entry, type2.Coverage)), LoadClassDefinition(Increment(lookup_entry, type2.ClassDefOffset)));
- case 3:
- ContextSubstFormat3 type3 = (ContextSubstFormat3)Marshal.PtrToStructure(lookup_entry, typeof(ContextSubstFormat3));
- type3.SubstFormat = SwapUInt16(type3.SubstFormat);
- type3.GlyphCount = SwapUInt16(type3.GlyphCount);
- type3.SubstitutionCount = SwapUInt16(type3.SubstitutionCount);
- Coverage[] coverages = new Coverage[type3.GlyphCount];
- SubstLookupRecord[] subRecords = new SubstLookupRecord[type3.SubstitutionCount];
- IntPtr type3_arrays = Increment(lookup_entry, Marshal.SizeOf(type3));
- for (int i = 0; i < type3.GlyphCount; i++)
- {
- ushort offset = (ushort)Marshal.PtrToStructure(type3_arrays, typeof(ushort));
- offset = SwapUInt16(offset);
- coverages[i] = LoadCoverage(Increment(lookup_entry, offset));
- type3_arrays = Increment(type3_arrays, Marshal.SizeOf(offset));
- }
- for (int i = 0; i < type3.SubstitutionCount; i++)
- {
- SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(type3_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = SwapUInt16(record.LookupListIndex);
- subRecords[i] = record;
- type3_arrays = Increment(type3_arrays, Marshal.SizeOf(record));
- }
- return new Contextual3(this, subRecords, coverages);
- }
- return new VoidSubstitution();
- }
- private Substitution LoadMultipleSubstitution(IntPtr lookup_entry)
- {
- MultipleSubstFormat1 type1 = (MultipleSubstFormat1)Marshal.PtrToStructure(lookup_entry, typeof(MultipleSubstFormat1));
- type1.SubstFormat = SwapUInt16(type1.SubstFormat);
- type1.Coverage = SwapUInt16(type1.Coverage);
- type1.SequenceCount = SwapUInt16(type1.SequenceCount);
- //type1.SequenceOffset = SwapUInt16(type1.SequenceOffset);
- IntPtr sequence_offset = Increment(lookup_entry, Marshal.SizeOf(type1));
- ushort[][] sequences = new ushort[type1.SequenceCount][];
- for (int i = 0; i < type1.SequenceCount; i++)
- {
- ushort offset = (ushort)Marshal.PtrToStructure(sequence_offset, typeof(ushort));
- offset = SwapUInt16(offset);
- IntPtr sequence_offset_table = Increment(lookup_entry, offset);
- ushort glyph_count = (ushort)Marshal.PtrToStructure(sequence_offset_table, typeof(ushort));
- glyph_count = SwapUInt16(glyph_count);
- ushort[] glyphs = new ushort[glyph_count];
- for (int j = 0; j < glyph_count; j++)
- {
- glyphs[j] = (ushort)Marshal.PtrToStructure(sequence_offset_table, typeof(ushort));
- glyphs[j] = SwapUInt16(glyphs[j]);
- sequence_offset_table = Increment(lookup_entry, Marshal.SizeOf(glyphs[j]));
- }
- sequences[i] = glyphs;
- sequence_offset = Increment(lookup_entry, Marshal.SizeOf(offset));
- }
- return new Multiple(sequences, LoadCoverage(Increment(lookup_entry, type1.Coverage)));
- //return new VoidSubstitution();
- }
- private Substitution LoadSingleSubstitution(IntPtr lookup_entry)
- {
- SignleSubstitutionFormat1 type1 = (SignleSubstitutionFormat1)Marshal.PtrToStructure(lookup_entry, typeof(SignleSubstitutionFormat1));
- type1.SubstFormat = SwapUInt16(type1.SubstFormat);
- type1.Coverage = SwapUInt16(type1.Coverage);
- type1.DeltaGlyphID = SwapInt16(type1.DeltaGlyphID);
- switch (type1.SubstFormat)
- {
- case 1:
- return new Single1(type1.DeltaGlyphID, LoadCoverage(Increment(lookup_entry, type1.Coverage)));
- case 2:
- ushort[] substitute = new ushort[type1.DeltaGlyphID];
- IntPtr lookup_entry_substitute = Increment(lookup_entry, Marshal.SizeOf(typeof(SignleSubstitutionFormat1)));
- for (int i = 0; i < type1.DeltaGlyphID; i++)
- {
- substitute[i] = (ushort)Marshal.PtrToStructure(lookup_entry_substitute, typeof(ushort));
- substitute[i] = SwapUInt16(substitute[i]);
- lookup_entry_substitute = Increment(lookup_entry_substitute, Marshal.SizeOf(typeof(ushort)));
- }
- return new Single2(substitute, LoadCoverage(Increment(lookup_entry, type1.Coverage)));
- }
- return new VoidSubstitution();
- }
- private ClassDefinition LoadClassDefinition(IntPtr class_definition_ptr)
- {
- ushort class_format = (ushort)Marshal.PtrToStructure(class_definition_ptr, typeof(ushort));
- class_format = SwapUInt16(class_format);
- switch (class_format)
- {
- case 1:
- ClassDefFormat1 type1 = (ClassDefFormat1)Marshal.PtrToStructure(class_definition_ptr, typeof(ClassDefFormat1));
- type1.ClassFormat = SwapUInt16(type1.ClassFormat);
- type1.GlyphCount = SwapUInt16(type1.GlyphCount);
- type1.StartGlyphID = SwapUInt16(type1.StartGlyphID);
- IntPtr class_value_array = Increment(class_definition_ptr, Marshal.SizeOf(type1));
- ushort[] classValues = new ushort[type1.GlyphCount];
- for (int i = 0; i < type1.GlyphCount; i++)
- {
- ushort classValue = (ushort)Marshal.PtrToStructure(class_value_array, typeof(ushort));
- classValue = SwapUInt16(classValue);
- class_value_array = Increment(class_value_array, Marshal.SizeOf(classValue));
- }
- return new ClassDefinition1(type1.StartGlyphID, classValues);
- case 2:
- ClassDefFormat2 type2 = (ClassDefFormat2)Marshal.PtrToStructure(class_definition_ptr, typeof(ClassDefFormat2));
- type2.ClassFormat = SwapUInt16(type2.ClassFormat);
- type2.ClassRangeCount = SwapUInt16(type2.ClassRangeCount);
- IntPtr class_records_array = Increment(class_definition_ptr, Marshal.SizeOf(type2));
- ClassRangeRecord[] records = new ClassRangeRecord[type2.ClassRangeCount];
- for (int i = 0; i < type2.ClassRangeCount; i++)
- {
- ClassRangeRecord record = (ClassRangeRecord)Marshal.PtrToStructure(class_records_array, typeof(ClassRangeRecord));
- record.StartGlyphID = SwapUInt16(record.StartGlyphID);
- record.EndGlyphID = SwapUInt16(record.EndGlyphID);
- record.ClassValue = SwapUInt16(record.ClassValue);
- class_records_array = Increment(class_records_array, Marshal.SizeOf(record));
- records[i] = record;
- }
- return new ClassDefinition2(records);
- }
- return new VoidClassDefinition();
- }
- private Coverage LoadCoverage(IntPtr coverage_table_ptr)
- {
- CoverageHeader ch = (CoverageHeader)Marshal.PtrToStructure(coverage_table_ptr, typeof(CoverageHeader));
- ch.CoverageFormat = SwapUInt16(ch.CoverageFormat);
- ch.GlyphCount = SwapUInt16(ch.GlyphCount);
- switch (ch.CoverageFormat)
- {
- case 1:
- {
- ushort[] glyphs = new ushort[ch.GlyphCount];
- coverage_table_ptr = Increment(coverage_table_ptr, Marshal.SizeOf(ch));
- for (int i = 0; i < ch.GlyphCount; i++)
- {
- glyphs[i] = SwapUInt16((ushort)Marshal.PtrToStructure(coverage_table_ptr, typeof(ushort)));
- coverage_table_ptr = Increment(coverage_table_ptr, Marshal.SizeOf(typeof(ushort)));
- }
- /*if((new Coverage1(ch.GlyphCount, glyphs)).IsSubstituteGetIndex(296) >=0)
- {
- //to do remove
- }*/
- return new Coverage1(ch.GlyphCount, glyphs);
- }
- //break;
- case 2:
- {
- RangeRecord[] rrs = new RangeRecord[ch.GlyphCount];
- coverage_table_ptr = Increment(coverage_table_ptr, Marshal.SizeOf(ch));
- for (int i = 0; i < ch.GlyphCount; i++)
- {
- rrs[i] = (RangeRecord)Marshal.PtrToStructure(coverage_table_ptr, typeof(RangeRecord));
- rrs[i].Start = SwapUInt16(rrs[i].Start);
- rrs[i].End = SwapUInt16(rrs[i].End);
- rrs[i].StartCoverageIndex = SwapUInt16(rrs[i].StartCoverageIndex);
- coverage_table_ptr = Increment(coverage_table_ptr, Marshal.SizeOf(rrs[i]));
- }
- /*if ((new Coverage2(ch.GlyphCount, rrs)).IsSubstituteGetIndex(296) >= 0)
- {
- //to do remove
- }*/
- return new Coverage2(ch.GlyphCount, rrs);
- }
- //break;
- }
- return new VoidCoverage();
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct ExtensionSubstFormat
- {
- [FieldOffset(0)]
- public ushort SubstFormat;
- [FieldOffset(2)]
- public ushort ExtensionLookupType;
- [FieldOffset(4)]
- public uint ExtensionOffset;
- public override string ToString()
- {
- return ((LookupTypes)ExtensionLookupType).ToString();
- }
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct LigatureSubst
- {
- [FieldOffset(0)]
- public ushort SubstFormat; // Format identifier-format = 1
- [FieldOffset(2)]
- public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
- [FieldOffset(4)]
- public ushort LigSetCount; // Number of LigatureSet tables
- // public ushort [LigSetCount] Array of offsets to LigatureSet tables-from beginning of Substitution table-ordered by Coverage Index
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct LigatureHeader
- {
- [FieldOffset(0)]
- public ushort LigGlyph; // GlyphID of ligature to substitute
- [FieldOffset(2)]
- public ushort CompCount; // Number of components in the ligature
- }
- internal Substitution LoadLigaturesSubtable(IntPtr lookup_entry)
- {
- LigatureSubst type4 = (LigatureSubst)Marshal.PtrToStructure(lookup_entry, typeof(LigatureSubst));
- type4.SubstFormat = SwapUInt16(type4.SubstFormat);
- type4.Coverage = SwapUInt16(type4.Coverage);
- type4.LigSetCount = SwapUInt16(type4.LigSetCount);
- //To do not null
- //LoadCoverageTable(null, Increment(lookup_entry, type4.Coverage));
- Coverage coverage = LoadCoverage(Increment(lookup_entry, type4.Coverage));
- // Ligature Set
- IntPtr ligature_set_ptr = Increment(lookup_entry, Marshal.SizeOf(type4));
- IntPtr current_ptr = ligature_set_ptr;
- IntPtr[] LigatureSet = new IntPtr[type4.LigSetCount];
- LigatureSet[][] ligatureSets = new LigatureSet[type4.LigSetCount][];
- for (int i = 0; i < type4.LigSetCount; i++)
- {
- ushort offset = SwapUInt16((ushort)Marshal.PtrToStructure(current_ptr, typeof(ushort)));
- // Console.WriteLine("LigatresSet[" + i + "] at" + offset);
- LigatureSet[i] = Increment(lookup_entry, offset);
- // Ligature Table
- ushort LigatureCount = SwapUInt16((ushort)Marshal.PtrToStructure(LigatureSet[i], typeof(ushort)));
- IntPtr ligature_ptr = Increment(LigatureSet[i], sizeof(ushort));
- IntPtr[] LigaturePtrs = new IntPtr[LigatureCount];
- LigatureHeader[] lh = new LigatureHeader[LigatureCount];
- ligatureSets[i] = new LigatureSet[LigatureCount];
- for (int j = 0; j < LigatureCount; j++)
- {
- ushort lig_offset = SwapUInt16((ushort)Marshal.PtrToStructure(ligature_ptr, typeof(ushort)));
- LigaturePtrs[j] = Increment(LigatureSet[i], lig_offset);
- // Console.WriteLine("\tLigature[" + j + "] at " + lig_offset);
- //// Ligature
- lh[j] = (LigatureHeader)Marshal.PtrToStructure(LigaturePtrs[j], typeof(LigatureHeader));
- lh[j].LigGlyph = SwapUInt16(lh[j].LigGlyph);
- lh[j].CompCount = SwapUInt16(lh[j].CompCount);
- ushort[] glyphs = new ushort[lh[j].CompCount - 1];
- IntPtr ligature_array = Increment(LigaturePtrs[j], Marshal.SizeOf(lh[j]));
- for (int k = 0; k < lh[j].CompCount - 1; k++)
- {
- glyphs[k] = SwapUInt16((ushort)Marshal.PtrToStructure(ligature_array, typeof(ushort)));
- ligature_array = Increment(ligature_array, Marshal.SizeOf(glyphs[k]));
- }
- //// ---------
- ligatureSets[i][j] = new LigatureSet(lh[j].LigGlyph, glyphs);
- ligature_ptr = Increment(ligature_ptr, sizeof(ushort));
- }
- // -----------------
- current_ptr = Increment(current_ptr, sizeof(ushort));
- }
- return new Ligature(coverage, ligatureSets);
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct CoverageHeader
- {
- [FieldOffset(0)]
- public ushort CoverageFormat; // Format identifier-format = 1
- [FieldOffset(2)]
- public ushort GlyphCount; // Number of glyphs in the GlyphArray
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct RangeRecord
- {
- [FieldOffset(0)]
- public ushort Start; // First GlyphID in the range
- [FieldOffset(2)]
- public ushort End; // Last GlyphID in the range
- [FieldOffset(4)]
- public ushort StartCoverageIndex; // Coverage Index of first GlyphID in range
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct SignleSubstitutionFormat1
- {
- [FieldOffset(0)]
- public ushort SubstFormat; // Format identifier-format = 1
- [FieldOffset(2)]
- public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
- [FieldOffset(4)]
- public short DeltaGlyphID; // Add to original GlyphID to get substitute GlyphID
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct MultipleSubstFormat1
- {
- [FieldOffset(0)]
- public ushort SubstFormat; // Format identifier-format = 1
- [FieldOffset(2)]
- public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
- [FieldOffset(4)]
- public ushort SequenceCount; // Number of Sequence table offsets in the Sequence array
- //[FieldOffset(6)]
- //public ushort SequenceOffset; // Array of offsets to Sequence tables-from beginning of Substitution table-ordered by Coverage Index
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct ContextSubstFormat1
- {
- [FieldOffset(0)]
- public ushort SubstFormat; // Format identifier-format = 1
- [FieldOffset(2)]
- public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
- [FieldOffset(4)]
- public ushort SubRuleSetCount; // Number of SubRuleSet tables — must equal glyphCount in Coverage table
- //[FieldOffset(6)]
- //public ushort[] subRuleSetOffsets; // Array of offsets to SubRuleSet tables. Offsets are from beginning of substitution subtable, ordered by Coverage index
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct ContextSubstFormat2
- {
- [FieldOffset(0)]
- public ushort SubstFormat; // Format identifier-format = 1
- [FieldOffset(2)]
- public ushort Coverage; // Offset to Coverage table-from beginning of Substitution table
- [FieldOffset(4)]
- public ushort ClassDefOffset; // Offset to glyph ClassDef table, from beginning of substitution subtable
- [FieldOffset(6)]
- public ushort SubClassSetCount; // Number of SubClassSet tables
- //[FieldOffset(8)]
- //public ushort[] subClassSetOffsets; // Array of offsets to SubClassSet tables. Offsets are from beginning of substitution subtable, ordered by class (may be NULL).
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct ContextSubstFormat3
- {
- [FieldOffset(0)]
- public ushort SubstFormat; // Format identifier-format = 1
- [FieldOffset(2)]
- public ushort GlyphCount; // Number of glyphs in the input glyph sequence
- [FieldOffset(4)]
- public ushort SubstitutionCount; // Number of SubstLookupRecords
- /*
- Offset16 coverageOffsets[glyphCount] Array of offsets to Coverage tables. Offsets are from beginning of substitution subtable, in glyph sequence order.
- SubstLookupRecord substLookupRecords[substitutionCount] Array of SubstLookupRecords, in design order.
- */
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct SubClassRule
- {
- [FieldOffset(0)]
- public ushort ClassCount;//GlyphCount; // Total number of classes specified for the context in the rule — includes the first class
- [FieldOffset(2)]
- public ushort SubstitutionCount; // Number of SubstLookupRecords
- /*
- uint16 inputSequence[glyphCount - 1] Array of classes to be matched to the input glyph sequence, beginning with the second glyph position.
- SubstLookupRecord substLookupRecords[substitutionCount] Array of Substitution lookups, in design order.
- */
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct SubstLookupRecord
- {
- [FieldOffset(0)]
- public ushort GlyphSequenceIndex; // Index into current glyph sequence — first glyph = 0.
- [FieldOffset(2)]
- public ushort LookupListIndex; // Lookup to apply to that position — zero-based index.
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct SubRuleTable
- {
- [FieldOffset(0)]
- public ushort GlyphCount; // Total number of glyphs in input glyph sequence — includes the first glyph.
- [FieldOffset(2)]
- public ushort SubstitutionCount; // Number of SubstLookupRecords
- //[FieldOffset(4)]
- //public ushort inputSequence; // [glyphCount - 1] Array of input glyph IDs — start with second glyph
- //[FieldOffset(6)]
- //public SubstLookupRecord[] substLookupRecords; // [substitutionCount] Array of SubstLookupRecords, in design order
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct SequenceFormat
- {
- [FieldOffset(0)]
- public ushort GlyphCount; // Number of glyph IDs in the Substitute array. This should always be greater than 0.
- // Substitute [GlyphCount] String of glyph IDs to substitute
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct ClassDefFormat1
- {
- [FieldOffset(0)]
- public ushort ClassFormat; // Format identifier — format = 1
- [FieldOffset(2)]
- public ushort StartGlyphID; // First glyph ID of the classValueArray
- [FieldOffset(4)]
- public ushort GlyphCount; // Size of the classValueArray
- //[FieldOffset(6)]
- //public ushort[] classValueArray; // [glyphCount] Array of Class Values — one per glyph ID
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct ClassDefFormat2
- {
- [FieldOffset(0)]
- public ushort ClassFormat; // Format identifier — format = 1
- [FieldOffset(2)]
- public ushort ClassRangeCount; // First glyph ID of the classValueArray
- //[FieldOffset(4)]
- //public ClassRangeRecord[] classRangeRecords; // Array of ClassRangeRecords — ordered by startGlyphID
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- public struct ClassRangeRecord
- {
- [FieldOffset(0)]
- public ushort StartGlyphID; // Format identifier — format = 1
- [FieldOffset(2)]
- public ushort EndGlyphID; // First glyph ID of the classValueArray
- [FieldOffset(4)]
- public ushort ClassValue; // Array of ClassRangeRecords — ordered by startGlyphID
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct ChainContextSubstFormat1
- {
- [FieldOffset(0)]
- public ushort SubstFormat; // Format identifier: format = 1
- [FieldOffset(2)]
- public ushort Coverage; // Offset to Coverage table, from beginning of substitution subtable.
- [FieldOffset(4)]
- public ushort ChainSubRuleSetCount; // Number of ChainSubRuleSet tables — must equal GlyphCount in Coverage table.
- /*
- Offset16 chainSubRuleSetOffsets[chainSubRuleSetCount] Array of offsets to ChainSubRuleSet tables. Offsets are from beginning of substitution subtable, ordered by Coverage index.
- */
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct ChainContextSubstFormat2
- {
- [FieldOffset(0)]
- public ushort SubstFormat; // Format identifier: format = 2
- [FieldOffset(2)]
- public ushort Coverage; // Offset to Coverage table, from beginning of substitution subtable.
- [FieldOffset(4)]
- public ushort BacktrackClassDefOffset; // Offset to glyph ClassDef table containing backtrack sequence data, from beginning of substitution subtable.
- [FieldOffset(6)]
- public ushort InputClassDefOffset; // Offset to glyph ClassDef table containing input sequence data, from beginning of substitution subtable.
- [FieldOffset(8)]
- public ushort LookaheadClassDefOffset; // Offset to glyph ClassDef table containing lookahead sequence data, from beginning of substitution subtable.
- [FieldOffset(10)]
- public ushort ChainSubClassSetCount; // Number of ChainSubClassSet tables
- /*
- Offset16 chainSubClassSetOffsets[chainSubClassSetCount] Array of offsets to ChainSubClassSet tables. Offsets are from beginning of substitution subtable, ordered by input class (may be NULL)
- */
- }
- [StructLayout(LayoutKind.Explicit, Pack = 1)]
- internal struct ChainContextSubstFormat3
- {
- [FieldOffset(0)]
- public ushort SubstFormat; // Format identifier: format = 3
- /*
- uint16 backtrackGlyphCount Number of glyphs in the backtracking sequence.
- Offset16 backtrackCoverageOffsets[backtrackGlyphCount] Array of offsets to coverage tables in backtracking sequence. Offsets are from beginning of substition subtable, in glyph sequence order.
- uint16 inputGlyphCount Number of glyphs in input sequence
- Offset16 inputCoverageOffsets[inputGlyphCount] Array of offsets to coverage tables in input sequence. Offsets are from beginning of substition subtable, in glyph sequence order.
- uint16 lookaheadGlyphCount Number of glyphs in lookahead sequence
- Offset16 lookaheadCoverageOffsets[lookaheadGlyphCount] Array of offsets to coverage tables in lookahead sequence. Offsets are from beginning of substitution subtable, in glyph sequence order.
- uint16 substitutionCount Number of SubstLookupRecords
- SubstLookupRecord substLookupRecords[substitutionCount] Array of SubstLookupRecords, in design order
- */
- }
- private Substitution LoadChainingContextSubstFormat1(IntPtr lookup_entry)
- {
- ChainContextSubstFormat1 type1 = (ChainContextSubstFormat1)Marshal.PtrToStructure(lookup_entry, typeof(ChainContextSubstFormat1));
- type1.SubstFormat = SwapUInt16(type1.SubstFormat);
- type1.ChainSubRuleSetCount = SwapUInt16(type1.ChainSubRuleSetCount);
- type1.Coverage = SwapUInt16(type1.Coverage);
- ChainingContextual1.ChainSubRule[][] chainSubRuleSets
- = new ChainingContextual1.ChainSubRule[type1.ChainSubRuleSetCount][];
- IntPtr chain_sub_rule_set_offsets = Increment(lookup_entry, Marshal.SizeOf(type1));
- for (int i = 0; i < type1.ChainSubRuleSetCount; i++)
- {
- ushort offset = (ushort)Marshal.PtrToStructure(chain_sub_rule_set_offsets, typeof(ushort));
- offset = SwapUInt16(offset);
- IntPtr chain_sub_rule_set_table = Increment(lookup_entry, offset);
- ushort count = (ushort)Marshal.PtrToStructure(chain_sub_rule_set_table, typeof(ushort));
- count = SwapUInt16(count);
- IntPtr chain_sub_rule_offset = Increment(chain_sub_rule_set_table, Marshal.SizeOf(count));
- ChainingContextual1.ChainSubRule[] chainSubRuleSet = new ChainingContextual1.ChainSubRule[count];
- for (int j = 0; j < count; j++)
- {
- ushort offset2 = (ushort)Marshal.PtrToStructure(chain_sub_rule_offset, typeof(ushort));
- offset2 = SwapUInt16(offset2);
- IntPtr chain_sub_rule_table = Increment(chain_sub_rule_set_table, offset2);
- IntPtr chain_sub_rule_arrays = chain_sub_rule_table;
- //start array
- ushort backtrackGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- backtrackGlyphCount = SwapUInt16(backtrackGlyphCount);
- ushort[] backtrackSequence = new ushort[backtrackGlyphCount];
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(backtrackGlyphCount));
- for (int k = 0; k < backtrackGlyphCount; k++)
- {
- ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- glyph = SwapUInt16(glyph);
- backtrackSequence[k] = glyph;
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
- }
- //end array
- //start array
- ushort inputGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- inputGlyphCount = SwapUInt16(inputGlyphCount);
- ushort[] inputSequence = new ushort[inputGlyphCount - 1];
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(inputGlyphCount));
- for (int k = 0; k < inputGlyphCount - 1; k++)
- {
- ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- glyph = SwapUInt16(glyph);
- inputSequence[k] = glyph;
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
- }
- //end array
- //start array
- ushort lookaheadGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- lookaheadGlyphCount = SwapUInt16(lookaheadGlyphCount);
- ushort[] lookAheadSequence = new ushort[lookaheadGlyphCount];
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(lookaheadGlyphCount));
- for (int k = 0; k < lookaheadGlyphCount; k++)
- {
- ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- glyph = SwapUInt16(glyph);
- lookAheadSequence[k] = glyph;
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
- }
- //end array
- //start array
- ushort substitutionCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- substitutionCount = SwapUInt16(substitutionCount);
- SubstLookupRecord[] records = new SubstLookupRecord[substitutionCount];
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(substitutionCount));
- for (int k = 0; k < substitutionCount; k++)
- {
- SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = SwapUInt16(record.LookupListIndex);
- records[k] = record;
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(record));
- }
- //end array
- chainSubRuleSet[j] = new ChainingContextual1.ChainSubRule(backtrackSequence, inputSequence, lookAheadSequence, records);
- chain_sub_rule_offset = Increment(chain_sub_rule_offset, Marshal.SizeOf(offset2));
- }
- chainSubRuleSets[i] = chainSubRuleSet;
- chain_sub_rule_set_offsets = Increment(chain_sub_rule_set_offsets, Marshal.SizeOf(offset));
- }
- return new ChainingContextual1(this, LoadCoverage(Increment(lookup_entry, type1.Coverage)), chainSubRuleSets);
- }
- private Substitution LoadChainingContextSubstFormat2(IntPtr lookup_entry)
- {
- ChainContextSubstFormat2 type2 = (ChainContextSubstFormat2)Marshal.PtrToStructure(lookup_entry, typeof(ChainContextSubstFormat2));
- type2.SubstFormat = SwapUInt16(type2.SubstFormat);
- type2.Coverage = SwapUInt16(type2.Coverage);
- type2.BacktrackClassDefOffset = SwapUInt16(type2.BacktrackClassDefOffset);
- type2.InputClassDefOffset = SwapUInt16(type2.InputClassDefOffset);
- type2.LookaheadClassDefOffset = SwapUInt16(type2.LookaheadClassDefOffset);
- type2.ChainSubClassSetCount = SwapUInt16(type2.ChainSubClassSetCount);
- IntPtr chain_sub_class_set_offsets = Increment(lookup_entry, Marshal.SizeOf(type2));
- ChainingContextual2.ChainSubClassRule[][] chainSubClassRuleSets
- = new ChainingContextual2.ChainSubClassRule[type2.ChainSubClassSetCount][];
- for (int i = 0; i < type2.ChainSubClassSetCount; i++)
- {
- ushort offset = (ushort)Marshal.PtrToStructure(chain_sub_class_set_offsets, typeof(ushort));
- offset = SwapUInt16(offset);
- if(offset == 0)
- {
- chain_sub_class_set_offsets = Increment(chain_sub_class_set_offsets, Marshal.SizeOf(offset));
- continue;
- }
- IntPtr chain_sub_class_set_table = Increment(lookup_entry, offset);
- ushort count = (ushort)Marshal.PtrToStructure(chain_sub_class_set_table, typeof(ushort));
- count = SwapUInt16(count);
- IntPtr chain_sub_class_offset = Increment(chain_sub_class_set_table, Marshal.SizeOf(count));
- ChainingContextual2.ChainSubClassRule[] chainSubClassSet = new ChainingContextual2.ChainSubClassRule[count];
- for (int j = 0; j < count; j++)
- {
- ushort offset2 = (ushort)Marshal.PtrToStructure(chain_sub_class_offset, typeof(ushort));
- offset2 = SwapUInt16(offset2);
- IntPtr chain_sub_rule_table = Increment(chain_sub_class_set_table, offset2);
- IntPtr chain_sub_rule_arrays = chain_sub_rule_table;
- //start array
- ushort backtrackGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- backtrackGlyphCount = SwapUInt16(backtrackGlyphCount);
- ushort[] backtrackSequence = new ushort[backtrackGlyphCount];
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(backtrackGlyphCount));
- for (int k = 0; k < backtrackGlyphCount; k++)
- {
- ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- glyph = SwapUInt16(glyph);
- backtrackSequence[k] = glyph;
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
- }
- //end array
- //start array
- ushort inputGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- inputGlyphCount = SwapUInt16(inputGlyphCount);
- ushort[] inputSequence = new ushort[inputGlyphCount - 1];
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(inputGlyphCount));
- for (int k = 0; k < inputGlyphCount - 1; k++)
- {
- ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- glyph = SwapUInt16(glyph);
- inputSequence[k] = glyph;
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
- }
- //end array
- //start array
- ushort lookaheadGlyphCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- lookaheadGlyphCount = SwapUInt16(lookaheadGlyphCount);
- ushort[] lookAheadSequence = new ushort[lookaheadGlyphCount];
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(lookaheadGlyphCount));
- for (int k = 0; k < lookaheadGlyphCount; k++)
- {
- ushort glyph = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- glyph = SwapUInt16(glyph);
- lookAheadSequence[k] = glyph;
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(glyph));
- }
- //end array
- //start array
- ushort substitutionCount = (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- substitutionCount = SwapUInt16(substitutionCount);
- SubstLookupRecord[] records = new SubstLookupRecord[substitutionCount];
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(substitutionCount));
- for (int k = 0; k < substitutionCount; k++)
- {
- SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = SwapUInt16(record.LookupListIndex);
- records[k] = record;
- chain_sub_rule_arrays = Increment(chain_sub_rule_arrays, Marshal.SizeOf(record));
- }
- //end array
- chainSubClassSet[j] = new ChainingContextual2.ChainSubClassRule(backtrackSequence, inputSequence, lookAheadSequence, records);
- chain_sub_class_offset = Increment(chain_sub_class_offset, Marshal.SizeOf(offset2));
- }
- chainSubClassRuleSets[i] = chainSubClassSet;
- chain_sub_class_set_offsets = Increment(chain_sub_class_set_offsets, Marshal.SizeOf(offset));
- }
- return new ChainingContextual2(this, chainSubClassRuleSets,
- LoadCoverage(Increment(lookup_entry, type2.Coverage)),
- LoadClassDefinition(Increment(lookup_entry, type2.BacktrackClassDefOffset)),
- LoadClassDefinition(Increment(lookup_entry, type2.InputClassDefOffset)),
- LoadClassDefinition(Increment(lookup_entry, type2.LookaheadClassDefOffset)));
- }
- private Substitution LoadChainingContextSubstFormat3(IntPtr lookup_entry)
- {
- IntPtr chain_format_3_array = Increment(lookup_entry, Marshal.SizeOf(typeof(ushort)));
- //start array
- ushort backtrackGlyphCount = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- backtrackGlyphCount = SwapUInt16(backtrackGlyphCount);
- Coverage[] backtrackSequence = new Coverage[backtrackGlyphCount];
- chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(backtrackGlyphCount));
- for (int k = 0; k < backtrackGlyphCount; k++)
- {
- ushort offset = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- offset = SwapUInt16(offset);
- backtrackSequence[k] = LoadCoverage(Increment(lookup_entry, offset));
- chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(offset));
- }
- //end array
- //start array
- ushort inputGlyphCount = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- inputGlyphCount = SwapUInt16(inputGlyphCount);
- Coverage[] inputSequence = new Coverage[inputGlyphCount];
- chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(inputGlyphCount));
- for (int k = 0; k < inputGlyphCount; k++)
- {
- ushort offset = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- offset = SwapUInt16(offset);
- inputSequence[k] = LoadCoverage(Increment(lookup_entry, offset));
- chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(offset));
- }
- //end array
- //start array
- ushort lookaheadGlyphCount = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- lookaheadGlyphCount = SwapUInt16(lookaheadGlyphCount);
- Coverage[] lookAheadSequence = new Coverage[lookaheadGlyphCount];
- chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(lookaheadGlyphCount));
- for (int k = 0; k < lookaheadGlyphCount; k++)
- {
- ushort offset = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- offset = SwapUInt16(offset);
- lookAheadSequence[k] = LoadCoverage(Increment(lookup_entry, offset));
- chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(offset));
- }
- //end array
- //start array
- ushort substitutionCount = (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- substitutionCount = SwapUInt16(substitutionCount);
- SubstLookupRecord[] records = new SubstLookupRecord[substitutionCount];
- chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(substitutionCount));
- for (int k = 0; k < substitutionCount; k++)
- {
- SubstLookupRecord record = (SubstLookupRecord)Marshal.PtrToStructure(chain_format_3_array, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = SwapUInt16(record.LookupListIndex);
- records[k] = record;
- chain_format_3_array = Increment(chain_format_3_array, Marshal.SizeOf(record));
- }
- //end array
- return new ChainingContextual3(this, records, backtrackSequence, inputSequence, lookAheadSequence);
- }
- #if DEBUG_TTF
- static int debug = 0;
- #endif
- //[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
- [System.Security.SecurityCritical]
- private Substitution LoadChainingContext(IntPtr lookup_entry)
- {
- try
- {
- ushort format = (ushort)Marshal.PtrToStructure(lookup_entry, typeof(ushort));
- format = SwapUInt16(format);
- #if DEBUG_TTF
- debug++;
- Console.WriteLine("LoadChainingContext format" + format.ToString() + " Iteration " + debug.ToString());
- if (debug == 123)
- ;
- #endif
- switch (format)
- {
- case 1:
- return LoadChainingContextSubstFormat1(lookup_entry);
- case 2:
- return LoadChainingContextSubstFormat2(lookup_entry);
- case 3:
- return LoadChainingContextSubstFormat3(lookup_entry);
- default:
- throw new NotSupportedException("Format of ChaingContext");
- }
- }
- catch (System.AccessViolationException e)
- {
- Console.WriteLine(e.StackTrace);
- }
- return new VoidSubstitution();
- }
- //[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
- [System.Security.SecurityCritical]
- internal override void Load(IntPtr font)
- {
- try
- {
- gsub_ptr = Increment(font, (int)this.Offset);
- header = (GSUB_Header)Marshal.PtrToStructure(gsub_ptr, typeof(GSUB_Header));
- ChangeEndian();
- LoadLookupList();
- LoadScriptList();
- //if(do_features) LoadFeatureList();
- #if DEBUG_TTF
- Console.WriteLine("=====================================================");
- #endif
- }
- catch (System.Exception e)
- {
- throw e;
- }
- //foreach (DictionaryEntry script in script_list)
- //{
- // Console.WriteLine(script.Key);
- // foreach (DictionaryEntry language in script.Value as Hashtable)
- // {
- // if (language.Key != "")
- // Console.WriteLine("\t" + language.Key);
- // else
- // Console.WriteLine("\tDEFAULT");
- // foreach (DictionaryEntry features in language.Value as Hashtable)
- // {
- // Console.WriteLine("\t\t" + features.Key /*+ "--> LookupTypes:" */ );
- // foreach (ushort offset in features.Value as ushort[])
- // {
- // LookupEntry le = (LookupEntry)lookup_list[offset];
- // // for (int i = 0; i < le.record_header.SubTableCount; i++)
- // {
- // Console.Write("\t\t\t");
- // switch ((LookupTypes)le.record_header.LookupType)
- // {
- // case LookupTypes.Single:
- // Console.WriteLine("Single");
- // break;
- // case LookupTypes.Multiple:
- // Console.WriteLine("Multiple");
- // break;
- // case LookupTypes.Alternate:
- // Console.WriteLine("Alternate");
- // break;
- // case LookupTypes.Ligature:
- // Console.WriteLine("Ligature");
- // break;
- // case LookupTypes.Context:
- // Console.WriteLine("Context");
- // break;
- // case LookupTypes.ChainingContext:
- // Console.WriteLine("ChainingContext");
- // break;
- // case LookupTypes.ExtensionSubstitution:
- // Console.WriteLine("ExtensionSubstitution");
- // break;
- // case LookupTypes.ReverseChainingContextSingle:
- // Console.WriteLine("ReverseChainingContextSingle");
- // break;
- // default:
- // Console.WriteLine("!!! Unknown lookup type");
- // break;
- // }
- // }
- // }
- // }
- // }
- //}
- //Console.WriteLine("=====================================================");
- }
- internal override uint Save(IntPtr font, uint offset)
- {
- this.Offset = offset;
- return base.Save(font, offset);
- }
- private void ChangeEndian()
- {
- header.Version = SwapUInt32(header.Version);
- header.ScriptList = SwapUInt16(header.ScriptList);
- header.LookupList = SwapUInt16(header.LookupList);
- header.FeatureList = SwapUInt16(header.FeatureList);
- }
- public GlyphSubstitutionClass(TrueTypeTable src) : base(src) { }
- internal List<ushort> ApplyGlyph(string script, string lang, ushort[] chars)
- {
- if (script == null)
- {
- script = "latn";
- foreach (string name in script_list.Keys)
- {
- script = name;
- break;
- }
- }
- if (script_list.ContainsKey(script))
- {
- Hashtable lang_sys_hash = script_list[script] as Hashtable;
- Hashtable lang_sys = null;
- if (lang_sys_hash.ContainsKey(lang))
- {
- lang_sys = lang_sys_hash[lang] as Hashtable;
- }
- else if (lang_sys_hash.ContainsKey(string.Empty))
- {
- lang_sys = lang_sys_hash[string.Empty] as Hashtable;
- }
- if (lang_sys != null)
- {
- switch (script)
- {
- case "arab":
- return ApplyGlyphArabic(lang_sys, chars);
- }
- }
- }
- return new List<ushort>(chars);
- }
- private void ApplyGlyphFeature(List<ushort> result, ushort[] offsets, ushort[] chars, ref int i)
- {
- foreach (ushort offset in offsets)
- {
- LookupEntry le = lookup_list[offset];
- for (int j = 0; j < le.subs.Length; j++)
- if (le.subs[j].Apply(result, chars, ref i))
- return;
- }
- result.Add(chars[i]);
- }
- private bool IsApplyGlyphFeature(int index, ushort[] offsets, ushort[] chars)
- {
- if (index < 0) return false;
- if (index >= chars.Length) return false;
- foreach (ushort offset in offsets)
- {
- LookupEntry le = lookup_list[offset];
- for (int j = 0; j < le.subs.Length; j++)
- if (le.subs[j].IsApply(chars, index) >= 0)
- return true;
- }
- return false;
- }
- private List<ushort> ApplyGlyphArabic(Hashtable lang_sys, ushort[] chars)
- {
- List<ushort> result = new List<ushort>();
- if (lang_sys.Contains("ccmp"))
- {
- ushort[] ccmp = lang_sys["ccmp"] as ushort[];
- for (int i = 0; i < chars.Length; i++)
- {
- ApplyGlyphFeature(result, ccmp, chars, ref i);
- }
- chars = result.ToArray();
- result.Clear();
- }
- ushort[] isol;
- if (lang_sys.Contains("isol")) isol = lang_sys["isol"] as ushort[];
- else isol = new ushort[0];
- ushort[] init;
- if (lang_sys.Contains("init")) init = lang_sys["init"] as ushort[];
- else init = new ushort[0];
- ushort[] medi;
- if (lang_sys.Contains("medi")) medi = lang_sys["medi"] as ushort[];
- else medi = new ushort[0];
- ushort[] fina;
- if (lang_sys.Contains("fina")) fina = lang_sys["fina"] as ushort[];
- else fina = new ushort[0];
- ArabicCharType[] types = new ArabicCharType[chars.Length];
- //Ýòî êîñòûëü, òàê êàê ÿ íå çíàþ êàêèì îáðàçîì âûòàùèòü íóæíûå èíäåêñû, ñäåëàþ òàêîé âàðèàíò áóäó ãóãëèòü
- for (int i = 0; i < chars.Length; i++)
- {
- bool nextMedi = IsApplyGlyphFeature(i + 1, medi, chars);
- bool nextFina = IsApplyGlyphFeature(i + 1, fina, chars);
- bool prevMedi = IsApplyGlyphFeature(i - 1, medi, chars);
- bool prevInit = IsApplyGlyphFeature(i - 1, init, chars);
- if (nextMedi || nextFina)
- {
- if (prevMedi || prevInit)
- {
- bool curMedi = IsApplyGlyphFeature(i, medi, chars);
- if (curMedi)
- {
- types[i] = ArabicCharType.Medi;
- continue;
- }
- }
- else
- {
- bool curInit = IsApplyGlyphFeature(i, init, chars);
- if (curInit)
- {
- types[i] = ArabicCharType.Init;
- continue;
- }
- }
- types[i] = ArabicCharType.None;
- continue;
- }
- if (prevInit || prevMedi)
- {
- bool curFina = IsApplyGlyphFeature(i, fina, chars);
- if (curFina)
- {
- types[i] = ArabicCharType.Fina;
- continue;
- }
- types[i] = ArabicCharType.None;
- continue;
- }
- if (!nextMedi && !nextFina && !prevInit && !prevMedi)
- {
- bool curIsol = IsApplyGlyphFeature(i, isol, chars);
- if (curIsol)
- {
- types[i] = ArabicCharType.Isol;
- continue;
- }
- types[i] = ArabicCharType.None;
- continue;
- }
- types[i] = ArabicCharType.None;
- }
- for (int i = 0; i < chars.Length; i++)
- {
- switch (types[i])
- {
- case ArabicCharType.None:
- result.Add(chars[i]);
- break;
- case ArabicCharType.Isol:
- ApplyGlyphFeature(result, isol, chars, ref i);
- break;
- case ArabicCharType.Fina:
- ApplyGlyphFeature(result, fina, chars, ref i);
- break;
- case ArabicCharType.Medi:
- ApplyGlyphFeature(result, medi, chars, ref i);
- break;
- case ArabicCharType.Init:
- ApplyGlyphFeature(result, init, chars, ref i);
- break;
- }
- }
- chars = result.ToArray();
- result.Clear();
- if (lang_sys.Contains("rlig"))
- {
- ushort[] rlig = lang_sys["rlig"] as ushort[];
- for (int i = 0; i < chars.Length; i++)
- {
- ApplyGlyphFeature(result, rlig, chars, ref i);
- }
- chars = result.ToArray();
- result.Clear();
- }
- if (lang_sys.Contains("calt"))
- {
- ushort[] calt = lang_sys["calt"] as ushort[];
- for (int i = 0; i < chars.Length; i++)
- {
- ApplyGlyphFeature(result, calt, chars, ref i);
- }
- chars = result.ToArray();
- result.Clear();
- }
- return new List<ushort>(chars);
- }
- enum ArabicCharType
- {
- None, Isol, Init, Medi, Fina
- }
- private ushort[] ApplySubstLookupRecord(ushort[] resultArr, SubstLookupRecord[] records)
- {
- List<ushort> result = new List<ushort>();
- for (int j = 0; j < records.Length; j++)
- {
- result.Clear();
- int resultIndex = 0;
- for (; resultIndex < records[j].GlyphSequenceIndex; resultIndex++)
- result.Add(resultArr[resultIndex]);
- LookupEntry le = lookup_list[records[j].LookupListIndex];
- for (int k = 0; k < le.subs.Length; k++)
- {
- if (le.subs[k].Apply(result, resultArr, ref resultIndex))
- {
- resultIndex += 1;
- break;
- }
- }
- for (; resultIndex < resultArr.Length; resultIndex++)
- result.Add(resultArr[resultIndex]);
- resultArr = result.ToArray();
- }
- return resultArr;
- }
- public interface Substitution
- {
- // need to index = index + step - 1;
- /// <summary>
- /// Return true if was applied
- /// </summary>
- /// <param name="list"></param>
- /// <param name="chars"></param>
- /// <param name="index"></param>
- /// <returns></returns>
- bool Apply(List<ushort> list, ushort[] chars, ref int index);
- /// <summary>
- /// Return coverageIndex for ApplyForce or if fail then return -1
- /// </summary>
- /// <param name="chars"></param>
- /// <param name="index"></param>
- /// <returns></returns>
- int IsApply(ushort[] chars, int index);
- /// <summary>
- /// Apply this Substitution with specified coverageIndex, cant be called only after IsApply
- /// </summary>
- /// <param name="list"></param>
- /// <param name="chars"></param>
- /// <param name="index"></param>
- /// <param name="coverageIndex"></param>
- void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex);
- IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types);
- }
- public interface Coverage
- {
- int IsSubstituteGetIndex(ushort ch);
- ushort[] GetGlyphs();
- ushort GetFirstGlyph();
- }
- public struct Coverage1 : Coverage
- {
- public ushort GlyphCount;
- public ushort[] Glyphs;
- public Coverage1(ushort glyphCount, ushort[] glyphs)
- {
- this.GlyphCount = glyphCount;
- this.Glyphs = glyphs;
- }
- public ushort GetFirstGlyph()
- {
- if (Glyphs.Length > 0)
- return Glyphs[0];
- return 1;
- }
- public ushort[] GetGlyphs()
- {
- return Glyphs;
- }
- public int IsSubstituteGetIndex(ushort ch)
- {
- for (int i = 0; i < GlyphCount; i++)
- {
- if (Glyphs[i] == ch)
- return i;
- }
- return -1;
- }
- }
- public struct Coverage2 : Coverage
- {
- public ushort GlyphCount;
- public RangeRecord[] RangeRecords;
- public Coverage2(ushort glyphCount, RangeRecord[] rangeRecords)
- {
- this.GlyphCount = glyphCount;
- this.RangeRecords = rangeRecords;
- }
- public ushort GetFirstGlyph()
- {
- if (RangeRecords.Length > 0)
- return RangeRecords[0].Start;
- return 1;
- }
- public ushort[] GetGlyphs()
- {
- Dictionary<int, ushort> results = new Dictionary<int, ushort>();
- for (int i = 0; i < RangeRecords.Length; i++)
- {
- for (int j = 0; j + RangeRecords[i].Start <= RangeRecords[i].End; j++)
- {
- results[j + RangeRecords[i].StartCoverageIndex] =
- (ushort)(RangeRecords[i].Start + j);
- }
- }
- ushort[] result = new ushort[results.Count];
- foreach (ushort key in results.Keys)
- {
- result[key] = results[key];
- }
- return result;
- }
- public int IsSubstituteGetIndex(ushort ch)
- {
- //var arr = RangeRecords.Select(a => a).OrderBy(a => a.StartCoverageIndex).ToArray();
- for (int i = 0; i < GlyphCount; i++)
- {
- if (RangeRecords[i].Start <= ch && RangeRecords[i].End >= ch)
- return RangeRecords[i].End - RangeRecords[i].Start + RangeRecords[i].StartCoverageIndex;
- }
- return -1;
- }
- }
- public struct Single1 : Substitution
- {
- public short DeltaGlyphIDOrGlyphCount;
- public Coverage Coverage;
- public Single1(short deltaGlyphID, Coverage coverage)
- {
- this.DeltaGlyphIDOrGlyphCount = deltaGlyphID;
- this.Coverage = coverage;
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- list.Add((ushort)(chars[index] + DeltaGlyphIDOrGlyphCount));
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.Single))
- yield break;
- ushort[] glyphs = Coverage.GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- yield return new KeyValuePair<ushort[], ushort[]>(
- new ushort[] { glyphs[i] },
- new ushort[] { (ushort)(glyphs[i] + DeltaGlyphIDOrGlyphCount) }
- );
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- return Coverage.IsSubstituteGetIndex(chars[index]);
- }
- }
- public struct Single2 : Substitution
- {
- public ushort[] Substitutes;
- public Coverage Coverage;
- public Single2(ushort[] substitutes, Coverage coverage)
- {
- this.Substitutes = substitutes;
- this.Coverage = coverage;
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- list.Add(Substitutes[coverageIndex]);
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.Single))
- yield break;
- ushort[] glyphs = Coverage.GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- yield return new KeyValuePair<ushort[], ushort[]>(
- new ushort[] { glyphs[i] },
- new ushort[] { Substitutes[i] }
- );
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- return Coverage.IsSubstituteGetIndex(chars[index]);
- }
- }
- public struct Multiple : Substitution
- {
- public ushort[][] Sequences;
- public Coverage Coverage;
- public Multiple(ushort[][] sequences, Coverage coverage)
- {
- this.Sequences = sequences;
- this.Coverage = coverage;
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- list.AddRange(Sequences[coverageIndex]);
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.Multiple))
- yield break;
- ushort[] glyphs = Coverage.GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- yield return new KeyValuePair<ushort[], ushort[]>(
- new ushort[] { glyphs[i] },
- Sequences[i]);
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- return Coverage.IsSubstituteGetIndex(chars[index]);
- }
- }
- public struct Ligature : Substitution
- {
- public Coverage Coverage;
- public LigatureSet[][] LigatureSets;
- LigatureSet LastSetIsApply;
- public Ligature(Coverage coverage, LigatureSet[][] ligatureSets)
- {
- this.Coverage = coverage;
- this.LigatureSets = ligatureSets;
- LastSetIsApply = new LigatureSet();
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- index += LastSetIsApply.Components.Length;
- list.Add(LastSetIsApply.LigGlyph);
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.Ligature))
- yield break;
- ushort[] glyphs = Coverage.GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- LigatureSet[] set = LigatureSets[i];
- for (int j = 0; j < set.Length; j++)
- {
- ushort[] key = new ushort[set[j].Components.Length + 1];
- key[0] = glyphs[i];
- for (int k = 0; k < set[j].Components.Length; k++)
- key[k + 1] = set[j].Components[k];
- yield return new KeyValuePair<ushort[], ushort[]>(
- key,
- new ushort[] { set[j].LigGlyph });
- }
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
- if (index2 >= 0)
- {
- LigatureSet[] sets = LigatureSets[index2];
- foreach (LigatureSet set in sets)
- {
- if (chars.Length - 1 - index - set.Components.Length >= 0)
- {
- bool flag = true;
- for (int i = 0; i < set.Components.Length; i++)
- {
- if (set.Components[i] != chars[index + 1 + i])
- {
- flag = false;
- break;
- }
- }
- if (flag)
- {
- LastSetIsApply = set;
- return index2;
- }
- }
- }
- }
- return -1;
- }
- }
- public struct LigatureSet
- {
- public ushort LigGlyph;
- public ushort[] Components;
- public LigatureSet(ushort ligGlyph, ushort[] components)
- {
- this.LigGlyph = ligGlyph;
- this.Components = components;
- }
- }
- public struct Contextual1 : Substitution
- {
- public struct SubRule
- {
- public ushort[] InputSequence;
- public SubstLookupRecord[] Records;
- public SubRule(ushort[] inputSequence, SubstLookupRecord[] records)
- {
- InputSequence = inputSequence;
- Records = records;
- }
- }
- public SubRule[][] SubRuleSets;
- public Coverage Coverage;
- private GlyphSubstitutionClass gsub_table;
- SubRule LastSubRuleIsApply;
- public Contextual1(GlyphSubstitutionClass gsub_table, SubRule[][] subRuleSets, Coverage coverage)
- {
- this.gsub_table = gsub_table;
- SubRuleSets = subRuleSets;
- Coverage = coverage;
- LastSubRuleIsApply = new SubRule();
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.Context))
- yield break;
- ushort[] glyphs = Coverage.GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- SubRule[] set = SubRuleSets[i];
- for (int j = 0; j < set.Length; j++)
- {
- ushort[] key = new ushort[set[j].InputSequence.Length + 1];
- key[0] = glyphs[i];
- for (int k = 0; k < set[j].InputSequence.Length; k++)
- key[k + 1] = set[j].InputSequence[k];
- yield return new KeyValuePair<ushort[], ushort[]>(
- key,
- gsub_table.ApplySubstLookupRecord(key, set[j].Records));
- }
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
- if (index2 >= 0)
- {
- SubRule[] subRules = SubRuleSets[index2];
- foreach (SubRule rule in subRules)
- {
- if (chars.Length - 1 - index - rule.InputSequence.Length >= 0)
- {
- bool flag = true;
- for (int i = 0; i < rule.InputSequence.Length; i++)
- {
- if (rule.InputSequence[i] != chars[index + 1 + i])
- {
- flag = false;
- break;
- }
- }
- if (flag)
- {
- LastSubRuleIsApply = rule;
- return index2;
- }
- }
- }
- }
- return -1;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- ushort[] resultArr = new ushort[LastSubRuleIsApply.InputSequence.Length + 1];
- for (int j = 0; j < resultArr.Length; j++)
- {
- resultArr[j] = chars[j + index];
- }
- list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, LastSubRuleIsApply.Records));
- index += LastSubRuleIsApply.InputSequence.Length;
- }
- }
- public struct Contextual2 : Substitution
- {
- public struct SubClassRule
- {
- public ushort[] InputSequence;
- public SubstLookupRecord[] Records;
- public SubClassRule(ushort[] inputSequence, SubstLookupRecord[] records)
- {
- InputSequence = inputSequence;
- Records = records;
- }
- }
- public SubClassRule[][] SubClassRuleSets;
- private GlyphSubstitutionClass gsub_table;
- public Coverage Coverage;
- public ClassDefinition ClassDefinition;
- SubClassRule LastSubClassRule;
- public Contextual2(GlyphSubstitutionClass gsub_table, SubClassRule[][] subClassRuleSets, Coverage coverage, ClassDefinition classDefinition)
- {
- this.gsub_table = gsub_table;
- SubClassRuleSets = subClassRuleSets;
- Coverage = coverage;
- ClassDefinition = classDefinition;
- LastSubClassRule = new SubClassRule();
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.Context))
- yield break;
- ushort[] glyphs = Coverage.GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- SubClassRule[] set = SubClassRuleSets[i];
- if (set != null)
- for (int j = 0; j < set.Length; j++)
- {
- ushort[] key = new ushort[set[j].InputSequence.Length + 1];
- key[0] = glyphs[i];
- for (int k = 0; k < set[j].InputSequence.Length; k++)
- key[k + 1] = ClassDefinition.GetFirstGlyphByClassValue(set[j].InputSequence[k]);
- yield return new KeyValuePair<ushort[], ushort[]>(
- key,
- gsub_table.ApplySubstLookupRecord(key, set[j].Records));
- }
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
- if (index2 >= 0)
- {
- SubClassRule[] subClassRules = SubClassRuleSets[index2];
- if (subClassRules != null)
- foreach (SubClassRule rule in subClassRules)
- {
- if (chars.Length - 1 - index - rule.InputSequence.Length >= 0)
- {
- bool flag = true;
- for (int i = 0; i < rule.InputSequence.Length; i++)
- {
- if (rule.InputSequence[i] != ClassDefinition.GetClassValue(chars[index + 1 + i]))
- {
- flag = false;
- break;
- }
- }
- if (flag)
- {
- LastSubClassRule = rule;
- return index2;
- }
- }
- }
- }
- return -1;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- ushort[] resultArr = new ushort[LastSubClassRule.InputSequence.Length + 1];
- for (int j = 0; j < resultArr.Length; j++)
- {
- resultArr[j] = chars[j + index];
- }
- list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, LastSubClassRule.Records));
- index += LastSubClassRule.InputSequence.Length;
- }
- }
- public struct Contextual3 : Substitution
- {
- public SubstLookupRecord[] Records;
- public Coverage[] Coverages;
- private GlyphSubstitutionClass gsub_table;
- public Contextual3(GlyphSubstitutionClass gsub_table, SubstLookupRecord[] records, Coverage[] coverages)
- {
- this.gsub_table = gsub_table;
- Records = records;
- Coverages = coverages;
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- ushort[] resultArr = new ushort[Coverages.Length];
- for (int j = 0; j < resultArr.Length; j++)
- {
- resultArr[j] = chars[j + index];
- }
- list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, Records));
- index += Coverages.Length - 1;
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.Context))
- yield break;
- if (Coverages.Length > 0)
- {
- ushort[] glyphs = Coverages[0].GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- ushort[] key = new ushort[Coverages.Length];
- key[0] = glyphs[i];
- for (int k = 1; k < Coverages.Length; k++)
- key[k] = Coverages[k].GetFirstGlyph();
- yield return new KeyValuePair<ushort[], ushort[]>(
- key,
- gsub_table.ApplySubstLookupRecord(key, Records));
- }
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- if (Coverages.Length > 0)
- {
- int index2 = Coverages[0].IsSubstituteGetIndex(chars[index]);
- if (index2 >= 0)
- {
- if (chars.Length - index - Coverages.Length >= 0)
- {
- bool flag = true;
- for (int i = 1; i < Coverages.Length; i++)
- {
- if (Coverages[i].IsSubstituteGetIndex(chars[index + i]) < 0)
- {
- flag = false;
- break;
- }
- }
- if (flag)
- {
- return index;
- }
- }
- }
- }
- return -1;
- }
- }
- public struct ChainingContextual1 : Substitution
- {
- public struct ChainSubRule
- {
- public ushort[] BacktrackSequence;
- public ushort[] InputSequence; // count -= 1;
- public ushort[] LookAheadSequence;
- public SubstLookupRecord[] Records;
- public ChainSubRule(ushort[] backtrackSequence, ushort[] inputSequence, ushort[] lookAheadSequence, SubstLookupRecord[] records)
- {
- BacktrackSequence = backtrackSequence;
- InputSequence = inputSequence;
- LookAheadSequence = lookAheadSequence;
- Records = records;
- }
- }
- public GlyphSubstitutionClass gsub_table;
- public ChainSubRule[][] ChainSubRuleSets;
- public Coverage Coverage;
- ChainSubRule LastChainSubRule;
- public ChainingContextual1(GlyphSubstitutionClass gsub_table, Coverage coverage, ChainSubRule[][] chainSubRuleSets)
- {
- this.gsub_table = gsub_table;
- ChainSubRuleSets = chainSubRuleSets;
- Coverage = coverage;
- LastChainSubRule = new ChainSubRule();
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.ChainingContext))
- yield break;
- ushort[] glyphs = Coverage.GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- ChainSubRule[] set = ChainSubRuleSets[i];
- for (int j = 0; j < set.Length; j++)
- {
- ushort[] key = new ushort[set[j].InputSequence.Length + 1];
- key[0] = glyphs[i];
- for (int k = 0; k < set[j].InputSequence.Length; k++)
- key[k + 1] = set[j].InputSequence[k];
- yield return new KeyValuePair<ushort[], ushort[]>(
- key,
- gsub_table.ApplySubstLookupRecord(key, set[j].Records));
- }
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
- if (index2 >= 0)
- {
- ChainSubRule[] subRules = ChainSubRuleSets[index2];
- foreach (ChainSubRule rule in subRules)
- {
- if (chars.Length - 1 - index - rule.InputSequence.Length >= 0 &&
- chars.Length - 1 - index - rule.LookAheadSequence.Length - rule.InputSequence.Length >= 0 &&
- index >= rule.BacktrackSequence.Length)
- {
- bool flag = true;
- for (int i = 0; i < rule.InputSequence.Length; i++)
- {
- if (rule.InputSequence[i] != chars[index + 1 + i])
- {
- flag = false;
- break;
- }
- }
- if (flag)
- for (int i = 0; i < rule.BacktrackSequence.Length; i++)
- {
- if (rule.BacktrackSequence[i] != chars[index - i - 1])
- {
- flag = false;
- break;
- }
- }
- if (flag)
- for (int i = 0; i < rule.LookAheadSequence.Length; i++)
- {
- if (rule.LookAheadSequence[i] != chars[index + i + 1 + rule.InputSequence.Length])
- {
- flag = false;
- break;
- }
- }
- if (flag)
- {
- LastChainSubRule = rule;
- return index2;
- }
- }
- }
- }
- return -1;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- ushort[] resultArr = new ushort[LastChainSubRule.InputSequence.Length + 1];
- for (int j = 0; j < resultArr.Length; j++)
- {
- resultArr[j] = chars[j + index];
- }
- list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, LastChainSubRule.Records));
- index += LastChainSubRule.InputSequence.Length;
- }
- }
- public struct ChainingContextual2 : Substitution
- {
- public struct ChainSubClassRule
- {
- public ushort[] BacktrackSequence;
- public ushort[] InputSequence; // count -= 1;
- public ushort[] LookAheadSequence;
- public SubstLookupRecord[] Records;
- public ChainSubClassRule(ushort[] backtrackSequence, ushort[] inputSequence, ushort[] lookAheadSequence, SubstLookupRecord[] records)
- {
- BacktrackSequence = backtrackSequence;
- InputSequence = inputSequence;
- LookAheadSequence = lookAheadSequence;
- Records = records;
- }
- }
- public ChainSubClassRule[][] SubClassRuleSets;
- private GlyphSubstitutionClass gsub_table;
- public Coverage Coverage;
- public ClassDefinition BacktrackClassDefinition;
- public ClassDefinition InputClassDefinition;
- public ClassDefinition LookaheadClassDefinition;
- ChainSubClassRule LastChainSubClassRule;
- public ChainingContextual2(
- GlyphSubstitutionClass gsub_table,
- ChainSubClassRule[][] subClassRuleSets,
- Coverage coverage,
- ClassDefinition backtrackClassDefinition,
- ClassDefinition inputClassDefinition,
- ClassDefinition lookaheadClassDefinition)
- {
- this.gsub_table = gsub_table;
- SubClassRuleSets = subClassRuleSets;
- Coverage = coverage;
- BacktrackClassDefinition = backtrackClassDefinition;
- InputClassDefinition = inputClassDefinition;
- LookaheadClassDefinition = lookaheadClassDefinition;
- LastChainSubClassRule = new ChainSubClassRule();
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.ChainingContext))
- yield break;
- ushort[] glyphs = Coverage.GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- ChainSubClassRule[] set = SubClassRuleSets[i];
- if (set != null)
- for (int j = 0; j < set.Length; j++)
- {
- ushort[] key = new ushort[set[j].InputSequence.Length + 1];
- key[0] = glyphs[i];
- for (int k = 0; k < set[j].InputSequence.Length; k++)
- key[k + 1] = InputClassDefinition.GetFirstGlyphByClassValue(set[j].InputSequence[k]);
- yield return new KeyValuePair<ushort[], ushort[]>(
- key,
- gsub_table.ApplySubstLookupRecord(key, set[j].Records));
- }
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- int index2 = Coverage.IsSubstituteGetIndex(chars[index]);
- if (index2 >= 0)
- {
- ChainSubClassRule[] subClassRules = SubClassRuleSets[index2];
- if (subClassRules != null)
- foreach (ChainSubClassRule rule in subClassRules)
- {
- if (chars.Length - 1 - index - rule.InputSequence.Length >= 0 &&
- chars.Length - 1 - index - rule.LookAheadSequence.Length - rule.InputSequence.Length >= 0 &&
- index >= rule.BacktrackSequence.Length)
- {
- bool flag = true;
- for (int i = 0; i < rule.InputSequence.Length; i++)
- {
- if (rule.InputSequence[i] != InputClassDefinition.GetClassValue(chars[index + 1 + i]))
- {
- flag = false;
- break;
- }
- }
- if (flag)
- for (int i = 0; i < rule.BacktrackSequence.Length; i++)
- {
- if (rule.BacktrackSequence[i] != BacktrackClassDefinition.GetClassValue(chars[index - i - 1]))
- {
- flag = false;
- break;
- }
- }
- if (flag)
- for (int i = 0; i < rule.LookAheadSequence.Length; i++)
- {
- if (rule.LookAheadSequence[i] !=
- LookaheadClassDefinition.GetClassValue(
- chars[index + i + 1 + rule.InputSequence.Length]))
- {
- flag = false;
- break;
- }
- }
- if (flag)
- {
- LastChainSubClassRule = rule;
- return index2;
- }
- }
- }
- }
- return -1;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- ushort[] resultArr = new ushort[LastChainSubClassRule.InputSequence.Length + 1];
- for (int j = 0; j < resultArr.Length; j++)
- {
- resultArr[j] = chars[j + index];
- }
- list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, LastChainSubClassRule.Records));
- index += LastChainSubClassRule.InputSequence.Length;
- }
- }
- public struct ChainingContextual3 : Substitution
- {
- public SubstLookupRecord[] Records;
- public Coverage[] BacktrackCoverages;
- public Coverage[] InputCoverages;
- public Coverage[] LookaheadCoverages;
- private GlyphSubstitutionClass gsub_table;
- public ChainingContextual3(GlyphSubstitutionClass gsub_table, SubstLookupRecord[] records, Coverage[] backtrackCoverages, Coverage[] inputCoverages, Coverage[] lookaheadCoverages)
- {
- this.gsub_table = gsub_table;
- Records = records;
- BacktrackCoverages = backtrackCoverages;
- InputCoverages = inputCoverages;
- LookaheadCoverages = lookaheadCoverages;
- }
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- int index2 = IsApply(chars, index);
- if (index2 >= 0)
- {
- ApplyForce(list, chars, ref index, index2);
- return true;
- }
- return false;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- ushort[] resultArr = new ushort[InputCoverages.Length];
- for (int j = 0; j < resultArr.Length; j++)
- {
- resultArr[j] = chars[j + index];
- }
- list.AddRange(gsub_table.ApplySubstLookupRecord(resultArr, Records));
- index += InputCoverages.Length - 1;
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.ChainingContext))
- yield break;
- if (InputCoverages.Length > 0)
- {
- ushort[] glyphs = InputCoverages[0].GetGlyphs();
- for (int i = 0; i < glyphs.Length; i++)
- {
- ushort[] key = new ushort[InputCoverages.Length];
- key[0] = glyphs[i];
- if (InputCoverages.Length > 0)
- for (int k = 1; k < InputCoverages.Length; k++)
- key[k] = InputCoverages[k].GetFirstGlyph();
- yield return new KeyValuePair<ushort[], ushort[]>(
- key,
- gsub_table.ApplySubstLookupRecord(key, Records));
- }
- }
- }
- public int IsApply(ushort[] chars, int index)
- {
- if (InputCoverages.Length > 0)
- {
- int index2 = InputCoverages[0].IsSubstituteGetIndex(chars[index]);
- if (index2 >= 0)
- {
- if (chars.Length - 1 - index - InputCoverages.Length >= 0 &&
- chars.Length - 1 - index - LookaheadCoverages.Length - InputCoverages.Length >= 0 &&
- index >= BacktrackCoverages.Length)
- {
- bool flag = true;
- for (int i = 1; i < InputCoverages.Length; i++)
- {
- if (InputCoverages[i].IsSubstituteGetIndex(chars[index + i]) < 0)
- {
- flag = false;
- break;
- }
- }
- if (flag)
- for (int i = 0; i < BacktrackCoverages.Length; i++)
- {
- if (BacktrackCoverages[i].IsSubstituteGetIndex(chars[index - i - 1]) < 0)
- {
- flag = false;
- break;
- }
- }
- if (flag)
- for (int i = 0; i < LookaheadCoverages.Length; i++)
- {
- if (LookaheadCoverages[i].IsSubstituteGetIndex(
- chars[index + i + 1 + InputCoverages.Length]) < 0)
- {
- flag = false;
- break;
- }
- }
- if (flag)
- {
- return index2;
- }
- }
- }
- }
- return -1;
- }
- }
- public struct Extension : Substitution
- {
- public Substitution Substitution;
- public ushort LookupType;
- public ushort Format;
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- return Substitution.Apply(list, chars, ref index);
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- Substitution.ApplyForce(list, chars, ref index, coverageIndex);
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- if (types != null && !ExtFor2005.Contains(types, LookupTypes.ExtensionSubstitution))
- return new KeyValuePair<ushort[], ushort[]>[0];
- return Substitution.GetList(types);
- }
- public int IsApply(ushort[] chars, int index)
- {
- return Substitution.IsApply(chars, index);
- }
- }
- public struct VoidSubstitution : Substitution
- {
- public bool Apply(List<ushort> list, ushort[] chars, ref int index)
- {
- return false;
- }
- public void ApplyForce(List<ushort> list, ushort[] chars, ref int index, int coverageIndex)
- {
- }
- public IEnumerable<KeyValuePair<ushort[], ushort[]>> GetList(LookupTypes[] types)
- {
- yield break;
- }
- public int IsApply(ushort[] chars, int index)
- {
- return -1;
- }
- }
- internal IEnumerable<KeyValuePair<ushort[], ushort[]>> GetSubstitutions(string script, string language, string feature, LookupTypes[] types)
- {
- if (script_list.ContainsKey(script))
- {
- Hashtable lang_sys_hash = script_list[script] as Hashtable;
- Hashtable lang_sys = null;
- if (lang_sys_hash.ContainsKey(language))
- {
- lang_sys = lang_sys_hash[language] as Hashtable;
- }
- else if (lang_sys_hash.ContainsKey(string.Empty))
- {
- lang_sys = lang_sys_hash[string.Empty] as Hashtable;
- }
- if (lang_sys != null)
- {
- if (lang_sys.ContainsKey(feature))
- {
- foreach (ushort offset in (ushort[])lang_sys[feature])
- {
- LookupEntry le = (LookupEntry)lookup_list[offset];
- for (int i = 0; i < le.subs.Length; i++)
- {
- foreach (KeyValuePair<ushort[], ushort[]> sub in le.subs[i].GetList(types))
- yield return sub;
- }
- }
- }
- }
- }
- }
- public struct VoidCoverage : Coverage
- {
- public ushort GetFirstGlyph()
- {
- return 1;
- }
- public ushort[] GetGlyphs()
- {
- return new ushort[0];
- }
- public int IsSubstituteGetIndex(ushort ch)
- {
- return -1;
- }
- }
- public interface ClassDefinition
- {
- ushort GetClassValue(ushort glyph);
- ushort GetFirstGlyphByClassValue(ushort v);
- }
- public struct ClassDefinition1 : ClassDefinition
- {
- ushort StartGlyphId;
- ushort[] ClassValues;
- public ClassDefinition1(ushort startGlyphId, ushort[] classValues)
- {
- StartGlyphId = startGlyphId;
- ClassValues = classValues;
- }
- public ushort GetClassValue(ushort glyph)
- {
- int index = glyph - StartGlyphId;
- if (index >= 0 && index < ClassValues.Length)
- return ClassValues[index];
- return 0;
- }
- public ushort GetFirstGlyphByClassValue(ushort v)
- {
- for (int i = 0; i < ClassValues.Length; i++)
- if (ClassValues[i] == v)
- return (ushort)(StartGlyphId + i);
- return StartGlyphId;
- }
- }
- public struct ClassDefinition2 : ClassDefinition
- {
- ClassRangeRecord[] Records;
- public ClassDefinition2(ClassRangeRecord[] records)
- {
- Records = records;
- }
- public ushort GetClassValue(ushort glyph)
- {
- foreach (ClassRangeRecord record in Records)
- if (record.StartGlyphID <= glyph && record.EndGlyphID >= glyph)
- return record.ClassValue;
- return 0;
- }
- public ushort GetFirstGlyphByClassValue(ushort v)
- {
- foreach (ClassRangeRecord record in Records)
- if (record.ClassValue == v)
- return record.StartGlyphID;
- if (Records.Length > 0)
- return Records[0].StartGlyphID;
- return 0;
- }
- }
- public struct VoidClassDefinition : ClassDefinition
- {
- public ushort GetClassValue(ushort glyph)
- {
- return 0;
- }
- public ushort GetFirstGlyphByClassValue(ushort v)
- {
- //TODO
- //TO DO
- // WHAT TO DO??? just return zero value, let it be space plz :)
- return 1;
- }
- }
- }
- }
- #pragma warning restore
|