1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947 |
- 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 DefaultLangSysOffset; // 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 LangSysOffset; // 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 uint featureVariationsOffset;
- 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(FontStream stream, uint feature_idx, out string FeatureTag)
- {
- //IntPtr feature_list_table_ptr = Increment(gsub_ptr, (int)header.FeatureList);
- stream.Position = this.Offset + header.FeatureList;
- ushort feature_count = stream.ReadUInt16();// nSwapUInt16((ushort)Marshal.PtrToStructure(feature_list_table_ptr, typeof(ushort)));
- if (feature_idx >= feature_count)
- throw new Exception("Feature index out of bound");
- long feature_list_pos = stream.Position;
- // IntPtr feature_record_ptr = Increment(feature_list_table_ptr, (int)(sizeof(ushort) + feature_idx * 6));
- stream.Position = feature_list_pos + feature_idx * 6;
- FeatureRecord feature_record = new FeatureRecord(); // Marshal.PtrToStructure(feature_record_ptr, typeof(FeatureRecord));
- feature_record.FeatureTag = stream.ReadUInt32();
- feature_record.Feature = stream.ReadUInt16(); // SwapUInt16(feature_record.Feature);
- FeatureTag = "" +
- (char)(0xff & (feature_record.FeatureTag >> 24)) +
- (char)(0xff & (feature_record.FeatureTag >> 16)) +
- (char)(0xff & (feature_record.FeatureTag >> 8)) +
- (char)(0xff & feature_record.FeatureTag);
- // IntPtr feature_table_ptr = Increment(feature_list_table_ptr, feature_record.Feature);
- stream.Position = this.Offset + header.FeatureList + feature_record.Feature;
- FeatureTable feature_table = new FeatureTable(); // Marshal.PtrToStructure(feature_table_ptr, typeof(FeatureTable));
- feature_table.FeatureParams = stream.ReadUInt16();
- feature_table.LookupCount = stream.ReadUInt16(); // SwapUInt16(feature_table.LookupCount);
- // IntPtr lookup_list_ptr = Increment(feature_table_ptr, Marshal.SizeOf(feature_table));
- ushort[] OffsetLookupList = new ushort[feature_table.LookupCount];
- for (int i = 0; i < feature_table.LookupCount; i++)
- {
- ushort lookuip_index = stream.ReadUInt16(); // 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(FontStream stream /*IntPtr lang_sys_rec_ptr*/)
- {
- Hashtable Features = new Hashtable();
- LangSysTable lang_sys_table = new LangSysTable(); // Marshal.PtrToStructure(lang_sys_rec_ptr, typeof(LangSysTable));
- lang_sys_table.LookupOrder = stream.ReadUInt16(); // SwapUInt16(lang_sys_table.LookupOrder);
- lang_sys_table.ReqFeatureIndex = stream.ReadUInt16(); // SwapUInt16(lang_sys_table.ReqFeatureIndex);
- lang_sys_table.FeatureCount = stream.ReadUInt16();// 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] = stream.ReadUInt16(); // SwapUInt16((ushort)Marshal.PtrToStructure(feature_index_ptr, typeof(ushort)));
- for (int k = 0; k < lang_sys_table.FeatureCount; k++)
- {
- string FeatureTag;
- ushort[] LookupOffsets = LoadFeature(stream, 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(FontStream stream)
- {
- //IntPtr script_list_table_ptr = Increment(gsub_ptr, (int)header.ScriptList);
- long ls_pos = stream.Position = this.Offset + header.ScriptList;
- ScriptListTable script_list_table = new ScriptListTable(); // Marshal.PtrToStructure(script_list_table_ptr, typeof(ScriptListTable));
- script_list_table.CountScripts = stream.ReadUInt16();
- ScriptListRecord[] script_record = new ScriptListRecord[script_list_table.CountScripts];
- for (int i = 0; i < script_list_table.CountScripts; i++)
- {
- script_record[i].ScriptTag = stream.ReadUInt32();
- script_record[i].ScriptOffset = stream.ReadUInt16(); // SwapUInt16(script_record.ScriptOffset);
- }
- for (int i = 0; i < script_list_table.CountScripts; i++)
- {
- string ScriptTag = "" +
- (char)(0xff & (script_record[i].ScriptTag >> 24)) +
- (char)(0xff & (script_record[i].ScriptTag >> 16)) +
- (char)(0xff & (script_record[i].ScriptTag >> 8)) +
- (char)(0xff & script_record[i].ScriptTag);
- #if DEBUG_TTF
- Console.WriteLine("[" + ScriptTag + "]");
- #endif
- Hashtable lang_sys_hash = new Hashtable();
- script_list.Add(ScriptTag, lang_sys_hash);
- stream.Position = ls_pos + script_record[i].ScriptOffset;
- ScriptTable script_table = new ScriptTable(); // Marshal.PtrToStructure(script_table_ptr, typeof(ScriptTable));
- script_table.DefaultLangSysOffset = stream.ReadUInt16(); // SwapUInt16(script_table.DefaultLangSys);
- script_table.LangSysCount = stream.ReadUInt16(); // SwapUInt16(script_table.LangSysCount);
- LangSysRecord[] lang_sys_rec = new LangSysRecord[script_table.LangSysCount];
- for (int j = 0; j < script_table.LangSysCount; j++)
- {
- lang_sys_rec[j].LangSysTag = stream.ReadUInt32();
- lang_sys_rec[j].LangSysOffset = stream.ReadUInt16(); // SwapUInt16(lang_sys_rec.LangSys);
- }
- for (int j = 0; j < script_table.LangSysCount; j++)
- {
- string LangSysTag = "" +
- (char)(0xff & (lang_sys_rec[j].LangSysTag >> 24)) +
- (char)(0xff & (lang_sys_rec[j].LangSysTag >> 16)) +
- (char)(0xff & (lang_sys_rec[j].LangSysTag >> 8)) +
- (char)(0xff & lang_sys_rec[j].LangSysTag);
- #if DEBUG_TTF
- Console.WriteLine("\t\"" + LangSysTag + "\"");
- #endif
- stream.Position = ls_pos + script_record[i].ScriptOffset + lang_sys_rec[j].LangSysOffset;
- lang_sys_hash.Add(LangSysTag, LoadLanguageSystemTable(stream));
- }
- if (script_table.DefaultLangSysOffset != 0)
- {
- // lang_sys_rec_ptr = Increment(script_table_ptr, script_table.DefaultLangSys);
- stream.Position = ls_pos + script_record[i].ScriptOffset + script_table.DefaultLangSysOffset;
- #if DEBUG_TTF
- Console.WriteLine("\t\"!DEF\"");
- #endif
- lang_sys_hash.Add("", LoadLanguageSystemTable(stream /*lang_sys_rec_ptr*/));
- }
- }
- }
- [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)
- }
- /// <summary>
- /// Stream position must point to lookup record
- /// </summary>
- /// <param name="stream"></param>
- /// <param name="lookup_table_header"></param>
- private LookupEntry LoadLookupRecord(FontStream stream, ref LookupTableRecordHeader lookup_table_header)
- {
- ushort markFilteringSet = 0;
- long record_pos = stream.Position;
- LookupEntry result = new LookupEntry();
- // --------------------------
- lookup_table_header.LookupType = stream.ReadUInt16();
- lookup_table_header.LookupFlag = stream.ReadUInt16();
- lookup_table_header.SubTableCount = stream.ReadUInt16();
- result.record_header = lookup_table_header;
- ushort[] subtableOffsets = new ushort[lookup_table_header.SubTableCount];
- for (int j = 0; j < subtableOffsets.Length; j++)
- subtableOffsets[j] = stream.ReadUInt16();
- if (0 != (lookup_table_header.LookupFlag & 0x0010))
- markFilteringSet = stream.ReadUInt16();
- result.subs = new Substitution[subtableOffsets.Length];
- ushort hold_lookup_type = lookup_table_header.LookupType;
- for (int j = 0; j < subtableOffsets.Length; j++)
- {
- bool infinity = false;
- lookup_table_header.LookupType = hold_lookup_type;
- stream.Position = record_pos + subtableOffsets[j];
- loop_extension:
- switch ((LookupTypes)lookup_table_header.LookupType)
- {
- case LookupTypes.Single: // Single Substitution Format
- result.subs[j] = LoadSingleSubstitution(stream);
- continue;
- case LookupTypes.Multiple: // Multiple Substitution Format
- result.subs[j] = LoadMultipleSubstitution(stream);
- continue;
- case LookupTypes.Alternate:
- Console.WriteLine("TTF: Alternate format not supported\n");
- continue;
- case LookupTypes.Ligature: // Ligature Substitution Format
- result.subs[j] = LoadLigaturesSubtable(stream);
- continue;
- case LookupTypes.Context: //
- result.subs[j] = LoadContextSubstitution(stream);
- continue;
- case LookupTypes.ChainingContext: // Chained Contexts Substitution
- result.subs[j] = LoadChainingContext(stream);
- continue;
- case LookupTypes.ExtensionSubstitution: // Extension Substitution
- ushort substFormat = stream.ReadUInt16();
- ushort extensionLookupType = stream.ReadUInt16();
- uint extensionOffset = stream.ReadUInt32();
- if (substFormat != 1)
- Console.WriteLine("Detected extension of Extension Substitution in Lookup record\n");
- if (infinity)
- {
- Console.WriteLine("Infinity loop detected");
- continue;
- }
- stream.Position = record_pos + subtableOffsets[j] + extensionOffset;
- lookup_table_header.LookupType = extensionLookupType;
- infinity = true;
- goto loop_extension;
- default:
- Console.WriteLine("Lookup type is " + lookup_table_header.LookupType);
- break;
- }
- }
- return result;
- }
- private void LoadLookupList(FontStream stream)
- {
- stream.Position = this.Offset + header.LookupList;
- ushort LookupListCount = stream.ReadUInt16(); // SwapUInt16((ushort)Marshal.PtrToStructure(lookup_list_table_ptr, typeof(ushort)));
- ushort[] lookupOffsets = new ushort[LookupListCount];
- for (int i = 0; i < LookupListCount; i++)
- lookupOffsets[i] = stream.ReadUInt16();
- lookup_list = new LookupEntry[LookupListCount];
- LookupTableRecordHeader[] lookup_table_header = new LookupTableRecordHeader[LookupListCount];
- for (int i = 0; i < LookupListCount; i++)
- {
- stream.Position = this.Offset + header.LookupList + lookupOffsets[i];
- #if DEBUG_TTF
- //Console.WriteLine("index is {0}", i);
- if (i == 21)
- Console.WriteLine("Debug!");
- #endif
- lookup_list[i] = LoadLookupRecord(stream, ref lookup_table_header[i]);
- }
- }
- private Substitution LoadContextSubstitution(FontStream stream)
- {
- long lookup_entry = stream.Position;
- ushort format = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(lookup_entry, typeof(ushort));
- switch (format)
- {
- case 1:
- ContextSubstFormat1 type1 = new ContextSubstFormat1(); // Marshal.PtrToStructure(lookup_entry, typeof(ContextSubstFormat1));
- type1.SubstFormat = 1;
- type1.CoverageOffset = stream.ReadUInt16();
- type1.SubRuleSetCount = stream.ReadUInt16();
- ushort[] seqRuleSetOffsets = new ushort[type1.SubRuleSetCount];
- for (int k = 0; k < type1.SubRuleSetCount; k++)
- seqRuleSetOffsets[k] = stream.ReadUInt16();
- Contextual1.SubRule[][] subRuleSets = new Contextual1.SubRule[type1.SubRuleSetCount][];
- for (int i = 0; i < type1.SubRuleSetCount; i++)
- {
- if (seqRuleSetOffsets[i] == 0)
- {
- // offsets may be NULL
- continue;
- }
- stream.Position = lookup_entry + seqRuleSetOffsets[i];
- ushort subRuleCount = stream.ReadUInt16();
- ushort[] subrule_offsets = new ushort[subRuleCount];
- for (int j = 0; j < subRuleCount; j++)
- subrule_offsets[j] = stream.ReadUInt16();
- 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 = new SubRuleTable(); // Marshal.PtrToStructure(subrule_table, typeof(SubRuleTable));
- stream.Position = lookup_entry + subrule_offsets[j];
- subRule.GlyphCount = stream.ReadUInt16(); // SwapUInt16(subRule.GlyphCount);
- subRule.SubstitutionCount = stream.ReadUInt16(); // SwapUInt16(subRule.SubstitutionCount);
- ushort[] glyphs = new ushort[subRule.GlyphCount - 1];
- // IntPtr subrule_table_arrays = Increment(subrule_table, Marshal.SizeOf(subRule));
- for (int k = 0; k < subRule.GlyphCount - 1; k++)
- glyphs[k] = stream.ReadUInt16();
- SubstLookupRecord[] records = new SubstLookupRecord[subRule.SubstitutionCount];
- for (int k = 0; k < subRule.SubstitutionCount; k++)
- {
- SubstLookupRecord record = new SubstLookupRecord(); // Marshal.PtrToStructure(subrule_table_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = stream.ReadUInt16(); // SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = stream.ReadUInt16(); // SwapUInt16(record.LookupListIndex);
- records[k] = record;
- }
- subRuleSet[j] = new Contextual1.SubRule(glyphs, records);
- // subrule_offsets = Increment(subrule_offsets, Marshal.SizeOf(subRuleOffset));
- }
- subRuleSets[i] = subRuleSet;
- }
- stream.Position = lookup_entry + type1.CoverageOffset; ;
- return new Contextual1(this, subRuleSets, LoadCoverage(stream));
- case 2:
- ContextSubstFormat2 type2 = new ContextSubstFormat2(); // Marshal.PtrToStructure(lookup_entry, typeof(ContextSubstFormat2));
- type2.SubstFormat = 2; // SwapUInt16(type2.SubstFormat);
- type2.Coverage = stream.ReadUInt16(); // SwapUInt16(type2.Coverage);
- type2.ClassDefOffset = stream.ReadUInt16(); // SwapUInt16(type2.ClassDefOffset);
- type2.SubClassSetCount = stream.ReadUInt16(); // SwapUInt16(type2.SubClassSetCount);
- Contextual2.SubClassRule[][] subClassRuleSets = new Contextual2.SubClassRule[type2.SubClassSetCount][];
- long sub_class_set_offset = stream.Position;
- for (int i = 0; i < type2.SubClassSetCount; i++)
- {
- ushort offset = stream.ReadUInt16(); // (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);
- long sub_class_set_table = stream.Position;
- ushort count = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(sub_class_set_table, typeof(ushort));
- // IntPtr sub_class_rule_offset = Increment(sub_class_set_table, Marshal.SizeOf(count));
- long sub_class_rule_offset = stream.Position;
- Contextual2.SubClassRule[] subClassSet = new Contextual2.SubClassRule[count];
- for (int j = 0; j < count; j++)
- {
- ushort offset2 = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(sub_class_rule_offset, typeof(ushort));
- // IntPtr sub_class_rule_table = Increment(sub_class_set_table, offset2);
- long sub_class_rule_table = sub_class_set_table + offset2;
- SubClassRule subClassRule = new SubClassRule(); // Marshal.PtrToStructure(sub_class_rule_table, typeof(SubClassRule));
- //IntPtr subclassrule_table_arrays = Increment(sub_class_rule_table, Marshal.SizeOf(subClassRule));
- long subclassrule_table_arrays = sub_class_rule_table + 4;
- subClassRule.ClassCount = stream.ReadUInt16(); // SwapUInt16(subClassRule.ClassCount);
- subClassRule.SubstitutionCount = stream.ReadUInt16(); // SwapUInt16(subClassRule.SubstitutionCount);
- ushort[] glyphClassess = new ushort[subClassRule.ClassCount - 1];
- for (int k = 0; k < subClassRule.ClassCount - 1; k++)
- glyphClassess[k] = stream.ReadUInt16();
- SubstLookupRecord[] records = new SubstLookupRecord[subClassRule.SubstitutionCount];
- for (int k = 0; k < subClassRule.SubstitutionCount; k++)
- {
- SubstLookupRecord record = new SubstLookupRecord(); // Marshal.PtrToStructure(subclassrule_table_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = stream.ReadUInt16(); // SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = stream.ReadUInt16(); // SwapUInt16(record.LookupListIndex);
- records[k] = record;
- }
- subClassSet[j] = new Contextual2.SubClassRule(glyphClassess, records);
- // sub_class_rule_offset = Increment(sub_class_rule_offset, Marshal.SizeOf(offset2));
- sub_class_rule_offset += 2;
- }
- subClassRuleSets[i] = subClassSet;
- }
- // sub_class_set_offset = Increment(sub_class_set_offset, Marshal.SizeOf(offset));
- sub_class_set_offset += 2;
- }
- stream.Position = lookup_entry + type2.Coverage;
- Coverage coverage = LoadCoverage(stream);
- stream.Position = lookup_entry + type2.ClassDefOffset;
- ClassDefinition class_definition = LoadClassDefinition(stream);
- return new Contextual2(this, subClassRuleSets, coverage, class_definition);
- case 3:
- ContextSubstFormat3 type3 = new ContextSubstFormat3(); // Marshal.PtrToStructure(lookup_entry, typeof(ContextSubstFormat3));
- type3.SubstFormat = 3; // SwapUInt16(type3.SubstFormat);
- type3.GlyphCount = stream.ReadUInt16(); // SwapUInt16(type3.GlyphCount);
- type3.SubstitutionCount = stream.ReadUInt16(); // SwapUInt16(type3.SubstitutionCount);
- Coverage[] coverages = new Coverage[type3.GlyphCount];
- SubstLookupRecord[] subRecords = new SubstLookupRecord[type3.SubstitutionCount];
- ushort[] offsets3 = new ushort[type3.GlyphCount];
- for (int i = 0; i < type3.GlyphCount; i++)
- offsets3[i] = stream.ReadUInt16();
- long type3_arrays = stream.Position;
- for (int i = 0; i < type3.GlyphCount; i++)
- {
- stream.Position = lookup_entry + offsets3[i];
- coverages[i] = LoadCoverage(stream);
- }
- stream.Position = type3_arrays;
- for (int i = 0; i < type3.SubstitutionCount; i++)
- {
- SubstLookupRecord record = new SubstLookupRecord(); // Marshal.PtrToStructure(type3_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = stream.ReadUInt16(); // SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = stream.ReadUInt16(); // 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(FontStream stream)
- {
- long lookup_entry = stream.Position;
- MultipleSubstFormat1 type1 = new MultipleSubstFormat1(); // Marshal.PtrToStructure(lookup_entry, typeof(MultipleSubstFormat1));
- type1.SubstFormat = stream.ReadUInt16(); // SwapUInt16(type1.SubstFormat);
- type1.Coverage = stream.ReadUInt16(); // SwapUInt16(type1.Coverage);
- type1.SequenceCount = stream.ReadUInt16(); // SwapUInt16(type1.SequenceCount);
- //type1.SequenceOffset = SwapUInt16(type1.SequenceOffset);
- ushort[][] sequences = new ushort[type1.SequenceCount][];
- for (int i = 0; i < type1.SequenceCount; i++)
- {
- ushort offset = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(sequence_offset, typeof(ushort));
- // offset = SwapUInt16(offset);
- // IntPtr sequence_offset_table = Increment(lookup_entry, offset);
- stream.Position = lookup_entry + offset;
- ushort glyph_count = stream.ReadUInt16(); // (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] = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(sequence_offset_table, typeof(ushort));
- glyphs[j] = stream.ReadUInt16(); // SwapUInt16(glyphs[j]);
- // sequence_offset_table = Increment(lookup_entry, Marshal.SizeOf(glyphs[j]));
- }
- sequences[i] = glyphs;
- //sequence_offset = Increment(lookup_entry, Marshal.SizeOf(offset));
- stream.Position = lookup_entry + 2;
- }
- stream.Position = lookup_entry + type1.Coverage;
- return new Multiple(sequences, LoadCoverage(stream));
- }
- private Substitution LoadSingleSubstitution(FontStream stream)
- {
- long lookup_entry = stream.Position;
- SignleSubstitutionFormat1 type1 = new SignleSubstitutionFormat1(); // Marshal.PtrToStructure(lookup_entry, typeof(SignleSubstitutionFormat1));
- type1.SubstFormat = stream.ReadUInt16(); // SwapUInt16(type1.SubstFormat);
- type1.Coverage = stream.ReadUInt16(); // SwapUInt16(type1.Coverage);
- type1.DeltaGlyphID = stream.ReadInt16(); // SwapInt16(type1.DeltaGlyphID);
- switch (type1.SubstFormat)
- {
- case 1:
- stream.Position = lookup_entry + type1.Coverage;
- return new Single1(type1.DeltaGlyphID, LoadCoverage(stream));
- 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] = stream.ReadUInt16();
- stream.Position = lookup_entry + type1.Coverage;
- return new Single2(substitute, LoadCoverage(stream));
- }
- return new VoidSubstitution();
- }
- private ClassDefinition LoadClassDefinition(FontStream stream)
- {
- long class_definition_ptr = stream.Position;
- ushort class_format = stream.ReadUInt16();
- class_format = SwapUInt16(class_format);
- switch (class_format)
- {
- case 1:
- ClassDefFormat1 type1 = new ClassDefFormat1(); // Marshal.PtrToStructure(class_definition_ptr, typeof(ClassDefFormat1));
- type1.ClassFormat = stream.ReadUInt16(); // SwapUInt16(type1.ClassFormat);
- type1.StartGlyphID = stream.ReadUInt16(); // SwapUInt16(type1.StartGlyphID);
- type1.GlyphCount = stream.ReadUInt16(); // SwapUInt16(type1.GlyphCount);
- ushort[] classValues = new ushort[type1.GlyphCount];
- for (int i = 0; i < type1.GlyphCount; i++)
- classValues[i] = stream.ReadUInt16(); ;
- return new ClassDefinition1(type1.StartGlyphID, classValues);
- case 2:
- ClassDefFormat2 type2 = new ClassDefFormat2(); // Marshal.PtrToStructure(class_definition_ptr, typeof(ClassDefFormat2));
- type2.ClassFormat = stream.ReadUInt16();
- type2.ClassRangeCount = stream.ReadUInt16();
- ClassRangeRecord[] records = new ClassRangeRecord[type2.ClassRangeCount];
- for (int i = 0; i < type2.ClassRangeCount; i++)
- {
- ClassRangeRecord record = new ClassRangeRecord(); // Marshal.PtrToStructure(class_records_array, typeof(ClassRangeRecord));
- record.StartGlyphID = stream.ReadUInt16();
- record.EndGlyphID = stream.ReadUInt16();
- record.ClassValue = stream.ReadUInt16();
- records[i] = record;
- }
- return new ClassDefinition2(records);
- }
- return new VoidClassDefinition();
- }
- private Coverage LoadCoverage(FontStream stream)
- {
- CoverageHeader ch = new CoverageHeader(); // Marshal.PtrToStructure(coverage_table_ptr, typeof(CoverageHeader));
- ch.CoverageFormat = stream.ReadUInt16(); // SwapUInt16(ch.CoverageFormat);
- ch.GlyphCount = stream.ReadUInt16(); // 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] = stream.ReadUInt16();
- }
- /*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] = new RangeRecord(); // Marshal.PtrToStructure(coverage_table_ptr, typeof(RangeRecord));
- rrs[i].Start = stream.ReadUInt16(); // SwapUInt16(rrs[i].Start);
- rrs[i].End = stream.ReadUInt16(); // SwapUInt16(rrs[i].End);
- rrs[i].StartCoverageIndex = stream.ReadUInt16(); // 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(FontStream stream)
- {
- long lookup_entry = stream.Position;
- LigatureSubst type4 = new LigatureSubst(); // Marshal.PtrToStructure(lookup_entry, typeof(LigatureSubst));
- type4.SubstFormat = stream.ReadUInt16(); // SwapUInt16(type4.SubstFormat);
- type4.Coverage = stream.ReadUInt16(); // SwapUInt16(type4.Coverage);
- type4.LigSetCount = stream.ReadUInt16(); // SwapUInt16(type4.LigSetCount);
- //To do not null
- //LoadCoverageTable(null, Increment(lookup_entry, type4.Coverage));
- stream.Position = lookup_entry + type4.Coverage;
- Coverage coverage = LoadCoverage(stream);
- // Ligature Set
- // IntPtr ligature_set_ptr = Increment(lookup_entry, Marshal.SizeOf(type4));
- stream.Position = lookup_entry + 6;
- //IntPtr current_ptr = ligature_set_ptr;
- //long current_ptr = lookup_entry + 6;
- // IntPtr[] LigatureSet = new IntPtr[type4.LigSetCount];
- ushort[] LigatureSet = new ushort[type4.LigSetCount];
- for (int i = 0; i < type4.LigSetCount; i++)
- LigatureSet[i] = stream.ReadUInt16();
- LigatureSet[][] ligatureSets = new LigatureSet[type4.LigSetCount][];
- for (int i = 0; i < type4.LigSetCount; i++)
- {
- //ushort offset = stream.ReadUInt16(); // SwapUInt16((ushort)Marshal.PtrToStructure(current_ptr, typeof(ushort)));
- // Console.WriteLine("LigatresSet[" + i + "] at" + offset);
- // LigatureSet[i] = stream.ReadUInt16(); // Increment(lookup_entry, offset);
- // Ligature Table
- stream.Position = lookup_entry + LigatureSet[i];
- long current_ptr = stream.Position;
- ushort LigatureCount = stream.ReadUInt16(); // 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];
- ushort[] lig_offsets = new ushort[LigatureCount];
- for (int j = 0; j < LigatureCount; j++)
- lig_offsets[j] = stream.ReadUInt16();
- for (int j = 0; j < LigatureCount; j++)
- {
- // ushort lig_offset = stream.ReadUInt16(); // SwapUInt16((ushort)Marshal.PtrToStructure(ligature_ptr, typeof(ushort)));
- //LigaturePtrs[j] = Increment(LigatureSet[i], lig_offset);
- // Console.WriteLine("\tLigature[" + j + "] at " + lig_offset);
- // stream.Position = current_ptr + LigatureSet[j] + lig_offsets[j];
- // stream.Position = lookup_entry + LigatureSet[i] + lig_offsets[j];
- stream.Position = current_ptr + lig_offsets[j];
- //// Ligature
- lh[j] = new LigatureHeader(); // Marshal.PtrToStructure(LigaturePtrs[j], typeof(LigatureHeader));
- lh[j].LigGlyph = stream.ReadUInt16(); // SwapUInt16(lh[j].LigGlyph);
- lh[j].CompCount = stream.ReadUInt16(); // SwapUInt16(lh[j].CompCount);
- ushort[] glyphs = new ushort[lh[j].CompCount - 1];
- for (int k = 0; k < lh[j].CompCount - 1; k++)
- glyphs[k] = stream.ReadUInt16(); // SwapUInt16((ushort)Marshal.PtrToStructure(ligature_array, typeof(ushort)));
- //// ---------
- ligatureSets[i][j] = new LigatureSet(lh[j].LigGlyph, glyphs);
- }
- // -----------------
- }
- 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 CoverageOffset; // 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 CoverageOffset; // 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(FontStream stream)
- {
- long lookup_entry = stream.Position - 2;
- ChainContextSubstFormat1 type1 = new ChainContextSubstFormat1(); // Marshal.PtrToStructure(lookup_entry, typeof(ChainContextSubstFormat1));
- // type1.SubstFormat = stream.ReadUInt16(); // SwapUInt16(type1.SubstFormat);
- type1.Coverage = stream.ReadUInt16(); // SwapUInt16(type1.Coverage);
- type1.ChainSubRuleSetCount = stream.ReadUInt16(); // SwapUInt16(type1.ChainSubRuleSetCount);
- ChainingContextual1.ChainSubRule[][] chainSubRuleSets
- = new ChainingContextual1.ChainSubRule[type1.ChainSubRuleSetCount][];
- //IntPtr chain_sub_rule_set_offsets = Increment(lookup_entry, Marshal.SizeOf(type1));
- long chain_sub_rule_set_offsets = stream.Position;
- ushort[] offsets = new ushort[type1.ChainSubRuleSetCount];
- for (int i = 0; i < type1.ChainSubRuleSetCount; i++)
- offsets[i] = stream.ReadUInt16();
- for (int i = 0; i < type1.ChainSubRuleSetCount; i++)
- {
- long stream_position = stream.Position;
- stream.Position = lookup_entry + offsets[i];
- ushort count = stream.ReadUInt16();
- long chain_sub_rule_offset = stream.Position;
- ushort[] offset2 = new ushort[count]; // (ushort)Marshal.PtrToStructure(chain_sub_rule_offset, typeof(ushort));
- for (int j = 0; j < count; j++)
- offset2[j] = stream.ReadUInt16();
- //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++)
- {
- stream.Position = lookup_entry + offsets[i] + offset2[j];
- ushort backtrackGlyphCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- ushort[] backtrackSequence = new ushort[backtrackGlyphCount];
- for (int k = 0; k < backtrackGlyphCount; k++)
- backtrackSequence[k] = stream.ReadUInt16();
- //end array
- //start array
- ushort inputGlyphCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- 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++)
- inputSequence[k] = stream.ReadUInt16(); ;
- //end array
- //start array
- ushort lookaheadGlyphCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- ushort[] lookAheadSequence = new ushort[lookaheadGlyphCount];
- for (int k = 0; k < lookaheadGlyphCount; k++)
- lookAheadSequence[k] = stream.ReadUInt16();
- //end array
- //start array
- ushort substitutionCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- SubstLookupRecord[] records = new SubstLookupRecord[substitutionCount];
- for (int k = 0; k < substitutionCount; k++)
- {
- SubstLookupRecord record = new SubstLookupRecord(); // Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = stream.ReadUInt16(); // SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = stream.ReadUInt16(); // SwapUInt16(record.LookupListIndex);
- records[k] = record;
- }
- //end array
- chainSubRuleSet[j] = new ChainingContextual1.ChainSubRule(backtrackSequence, inputSequence, lookAheadSequence, records);
- //chain_sub_rule_offset = Increment(chain_sub_rule_offset, Marshal.SizeOf(offset2));
- chain_sub_rule_offset += 2;
- }
- chainSubRuleSets[i] = chainSubRuleSet;
- // chain_sub_rule_set_offsets = Increment(chain_sub_rule_set_offsets, Marshal.SizeOf(offset));
- chain_sub_rule_set_offsets += 2;
- }
- stream.Position = lookup_entry + type1.Coverage;
- return new ChainingContextual1(this, LoadCoverage(stream), chainSubRuleSets);
- }
- private Substitution LoadChainingContextSubstFormat2(FontStream stream)
- {
- ChainContextSubstFormat2 type2 = new ChainContextSubstFormat2(); // Marshal.PtrToStructure(lookup_entry, typeof(ChainContextSubstFormat2));
- long lookup_entry = stream.Position - 2;
- //type2.SubstFormat = stream.ReadUInt16(); // SwapUInt16(type2.SubstFormat);
- type2.CoverageOffset = stream.ReadUInt16(); // SwapUInt16(type2.Coverage);
- type2.BacktrackClassDefOffset = stream.ReadUInt16(); // SwapUInt16(type2.BacktrackClassDefOffset);
- type2.InputClassDefOffset = stream.ReadUInt16(); // SwapUInt16(type2.InputClassDefOffset);
- type2.LookaheadClassDefOffset = stream.ReadUInt16(); // SwapUInt16(type2.LookaheadClassDefOffset);
- type2.ChainSubClassSetCount = stream.ReadUInt16(); // SwapUInt16(type2.ChainSubClassSetCount);
- ChainingContextual2.ChainSubClassRule[][] chainSubClassRuleSets
- = new ChainingContextual2.ChainSubClassRule[type2.ChainSubClassSetCount][];
- ushort[] offsets = new ushort[type2.ChainSubClassSetCount];
- for (int i = 0; i < type2.ChainSubClassSetCount; i++)
- offsets[i] = stream.ReadUInt16();
- for (int i = 0; i < type2.ChainSubClassSetCount; i++)
- {
- if (offsets[i] == 0)
- {
- // If no patterns are defined with an input sequence beginning with a particular class,
- // then the offset for that class value can be set to NULL.
- continue;
- }
- long chain_sub_class_ruleset_table = lookup_entry + offsets[i];
- stream.Position = chain_sub_class_ruleset_table;
- ushort count = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_sub_class_set_table, typeof(ushort));
- // 20231110: Read chainedClassSeqRuleOffsets
- ushort[] chainedClassSeqRuleOffsets = new ushort[count];
- for (int k = 0; k < count; k++)
- chainedClassSeqRuleOffsets[k] = stream.ReadUInt16();
- ChainingContextual2.ChainSubClassRule[] chainSubClassSet = new ChainingContextual2.ChainSubClassRule[count];
- for (int j = 0; j < count; j++)
- {
- stream.Position = chain_sub_class_ruleset_table + chainedClassSeqRuleOffsets[j];
- //start array
- ushort backtrackGlyphCount = stream.ReadUInt16();
- ushort[] backtrackSequence = new ushort[backtrackGlyphCount];
- for (int k = 0; k < backtrackGlyphCount; k++)
- backtrackSequence[k] = stream.ReadUInt16();
- //end array
- //start array
- ushort inputGlyphCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- ushort[] inputSequence = new ushort[inputGlyphCount - 1];
- for (int k = 0; k < inputGlyphCount - 1; k++)
- inputSequence[k] = stream.ReadUInt16();
- //end array
- //start array
- ushort lookaheadGlyphCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- ushort[] lookAheadSequence = new ushort[lookaheadGlyphCount];
- for (int k = 0; k < lookaheadGlyphCount; k++)
- lookAheadSequence[k] = stream.ReadUInt16();
- //end array
- //start array
- ushort substitutionCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(ushort));
- SubstLookupRecord[] records = new SubstLookupRecord[substitutionCount];
- for (int k = 0; k < substitutionCount; k++)
- {
- SubstLookupRecord record = new SubstLookupRecord(); // Marshal.PtrToStructure(chain_sub_rule_arrays, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = stream.ReadUInt16(); // SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = stream.ReadUInt16(); // SwapUInt16(record.LookupListIndex);
- records[k] = record;
- }
- //end array
- chainSubClassSet[j] = new ChainingContextual2.ChainSubClassRule(backtrackSequence, inputSequence, lookAheadSequence, records);
- }
- chainSubClassRuleSets[i] = chainSubClassSet;
- }
- stream.Position = lookup_entry + type2.CoverageOffset;
- Coverage coverage = LoadCoverage(stream);
- stream.Position = lookup_entry + type2.BacktrackClassDefOffset;
- ClassDefinition backtrackClassDefinition = LoadClassDefinition(stream);
- stream.Position = lookup_entry + type2.InputClassDefOffset;
- ClassDefinition inputClassDefinition = LoadClassDefinition(stream);
- stream.Position = lookup_entry + type2.LookaheadClassDefOffset;
- ClassDefinition lookaheadClassDefinition = LoadClassDefinition(stream);
- return new ChainingContextual2(this, chainSubClassRuleSets,
- coverage,
- backtrackClassDefinition,
- inputClassDefinition,
- lookaheadClassDefinition);
- }
- private Substitution LoadChainingContextSubstFormat3(FontStream stream)
- {
- long lookup_entry = stream.Position - 2;
- //IntPtr chain_format_3_array = Increment(lookup_entry, Marshal.SizeOf(typeof(ushort)));
- long chain_format_3_array = lookup_entry + 2;
- //start array
- ushort backtrackGlyphCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- ushort[] offsets = new ushort[backtrackGlyphCount];
- for (int k = 0; k < backtrackGlyphCount; k++)
- offsets[k] = stream.ReadUInt16();
- ushort inputGlyphCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- ushort[] offsets_gc = new ushort[inputGlyphCount];
- for (int k = 0; k < inputGlyphCount; k++)
- offsets_gc[k] = stream.ReadUInt16();
- ushort lookaheadGlyphCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- ushort[] offsets_as = new ushort[lookaheadGlyphCount];
- for (int k = 0; k < lookaheadGlyphCount; k++)
- offsets_as[k] = stream.ReadUInt16();
- ushort lookuoCount = stream.ReadUInt16(); // (ushort)Marshal.PtrToStructure(chain_format_3_array, typeof(ushort));
- long lookupPosition = stream.Position;
- //start array
- Coverage[] backtrackSequence = new Coverage[backtrackGlyphCount];
- for (int k = 0; k < backtrackGlyphCount; k++)
- {
- stream.Position = lookup_entry + offsets[k];
- backtrackSequence[k] = LoadCoverage(stream);
- }
- //end array
- //start array
- Coverage[] inputSequence = new Coverage[inputGlyphCount];
- for (int k = 0; k < inputGlyphCount; k++)
- {
- stream.Position = lookup_entry + offsets_gc[k];
- inputSequence[k] = LoadCoverage(stream);
- }
- //end array
- //start array
- Coverage[] lookAheadSequence = new Coverage[lookaheadGlyphCount];
- for (int k = 0; k < lookaheadGlyphCount; k++)
- {
- stream.Position = lookup_entry + offsets_as[k];
- lookAheadSequence[k] = LoadCoverage(stream);
- }
- //end array
- //start array
- stream.Position = lookupPosition;
- SubstLookupRecord[] records = new SubstLookupRecord[lookuoCount];
- for (int k = 0; k < lookuoCount; k++)
- {
- SubstLookupRecord record = new SubstLookupRecord(); // Marshal.PtrToStructure(chain_format_3_array, typeof(SubstLookupRecord));
- record.GlyphSequenceIndex = stream.ReadUInt16(); // SwapUInt16(record.GlyphSequenceIndex);
- record.LookupListIndex = stream.ReadUInt16(); // SwapUInt16(record.LookupListIndex);
- records[k] = record;
- }
- //end array
- return new ChainingContextual3(this, records, backtrackSequence, inputSequence, lookAheadSequence);
- }
- #if DEBUG_TTF
- static int debug = 0;
- #endif
- private Substitution LoadChainingContext(FontStream stream)
- {
- // long lookup_entry = stream.Position;
- ushort format = stream.ReadUInt16();
- #if DEBUG_TTF
- debug++;
- Console.WriteLine("LoadChainingContext format" + format.ToString() + " Iteration " + debug.ToString());
- if (debug == 123)
- ;
- #endif
- switch (format)
- {
- case 1:
- return LoadChainingContextSubstFormat1(stream);
- case 2:
- return LoadChainingContextSubstFormat2(stream);
- case 3:
- return LoadChainingContextSubstFormat3(stream);
- default:
- throw new NotSupportedException("Format of GSUB ChaingContext");
- }
- return new VoidSubstitution();
- }
- internal override void Load(FontStream stream)
- {
- stream.Seek(this.Offset, System.IO.SeekOrigin.Begin);
- try
- {
- header.Version = stream.ReadUInt32(); // Version of the GSUB table-initially set to 0x00010000
- header.ScriptList = stream.ReadUInt16(); // Offset to ScriptList table-from beginning of GSUB table
- header.FeatureList = stream.ReadUInt16(); // Offset to FeatureList table-from beginning of GSUB table
- header.LookupList = stream.ReadUInt16(); // Offset to LookupList table-from beginning of GSUB table
- if (header.Version == 0x00010001)
- featureVariationsOffset = stream.ReadUInt32();
- LoadLookupList(stream);
- LoadScriptList(stream);
- //if(do_features) LoadFeatureList();
- }
- catch (System.IO.EndOfStreamException ex)
- {
- Console.WriteLine("End of stream exception");
- }
- }
- //internal override uint Save(FontStream 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
|