private IGlyphTransformationTable ParseCoverageChainingSubstitutionTable(int subTableOffset, dynamic fontTable, LookupFlags lookupFlags) { var type = typeof(GlyphTypeface).Assembly.GetType("MS.Internal.Shaping.CoverageChainingSubtable"); dynamic table = new AccessPrivateWrapper(TypeExtensions.Instantiate(type, fontTable.Wrapped, subTableOffset)); dynamic contextualLookupTable = new AccessPrivateWrapper(table.ContextualLookups(fontTable.Wrapped)); return(new ChainingCoverageContextSubstitutionTable { LookbackCoverages = this.GetEnumerableFromInternalList( () => table.BacktrackGlyphCount(fontTable.Wrapped), i => (ICoverageTable)this.ParseCoverageTable(fontTable, new AccessPrivateWrapper(table.BacktrackCoverage(fontTable.Wrapped, i)))).ToList(), ContextCoverages = this.GetEnumerableFromInternalList( () => table.InputGlyphCount(fontTable.Wrapped), i => (ICoverageTable)this.ParseCoverageTable(fontTable, new AccessPrivateWrapper(table.InputCoverage(fontTable.Wrapped, i)))).ToList(), LookaheadCoverages = this.GetEnumerableFromInternalList( () => table.LookaheadGlyphCount(fontTable.Wrapped), i => (ICoverageTable)this.ParseCoverageTable(fontTable, new AccessPrivateWrapper(table.LookaheadCoverage(fontTable.Wrapped, i)))).ToList(), TransformationSets = this.GetEnumerableFromInternalList( () => contextualLookupTable.recordCount, i => new ContextTransformationSet { FirstGlyphIndex = contextualLookupTable.SequenceIndex(fontTable.Wrapped, i), Transformations = this.GetTransformationTablesByLookupIndex(fontTable, contextualLookupTable.LookupIndex(fontTable.Wrapped, i)) }).ToList(), LookupFlags = lookupFlags }); }
private ContextTransformationRule ParseContextTransformationRule(dynamic fontTable, dynamic rule, Func <dynamic, int, ushort> idProjection) { dynamic contextualLookupsTable = new AccessPrivateWrapper(rule.ContextualLookups(fontTable.Wrapped)); return(new ContextTransformationRule { Context = this.GetEnumerableFromInternalList( () => rule.GlyphCount(fontTable.Wrapped), i => (ushort)idProjection(rule, i)).ToList(), TransformationSets = this.GetEnumerableFromInternalList( () => rule.SubstCount(fontTable.Wrapped), i => new ContextTransformationSet { FirstGlyphIndex = contextualLookupsTable.SequenceIndex(fontTable.Wrapped, i), Transformations = this.GetTransformationTablesByLookupIndex(fontTable, contextualLookupsTable.LookupIndex(fontTable.Wrapped, i)) }).ToList() }); }
private ChainingContextTransformationRule ParseChainingTransformationRule(dynamic fontTable, dynamic rule, Func <dynamic, int, ushort> idProjection, ushort firstInputId) { const int GlyphIdSize = 2; // Load the lookback var lookBackCount = rule.GlyphCount(fontTable.Wrapped, rule.offset); int currentOffset = rule.offset + rule.sizeCount; var lookBackGlyphIds = this.GetEnumerableFromInternalList( () => lookBackCount, i => (ushort)idProjection(rule, (i * GlyphIdSize) + currentOffset)).ToList(); currentOffset += lookBackCount * GlyphIdSize; // Load the context var contextCount = rule.GlyphCount(fontTable.Wrapped, currentOffset); currentOffset += rule.sizeCount; // The first element of the context comes from index of the rule set var contextGlyphIds = this.GetEnumerableFromInternalList( () => (ushort)(contextCount - 1), i => (ushort)idProjection(rule, (i * GlyphIdSize) + currentOffset)).Prepend(firstInputId).ToList(); currentOffset += (contextCount - 1) * GlyphIdSize; // Load the context var lookAheadCount = rule.GlyphCount(fontTable.Wrapped, currentOffset); currentOffset += rule.sizeCount; var lookAheadGlyphIds = this.GetEnumerableFromInternalList( () => lookAheadCount, i => (ushort)idProjection(rule, (i * GlyphIdSize) + currentOffset)).ToList(); currentOffset += lookAheadCount * GlyphIdSize; // Load the substitution lookup records var lookupSubstitutionRecordCount = fontTable.GetUShort(currentOffset); dynamic contextualLookupsTable = new AccessPrivateWrapper(rule.ContextualLookups(fontTable.Wrapped, currentOffset)); return(new ChainingContextTransformationRule { Lookback = lookBackGlyphIds, Context = contextGlyphIds, Lookahead = lookAheadGlyphIds, TransformationSets = this.GetEnumerableFromInternalList( () => lookupSubstitutionRecordCount, i => new ContextTransformationSet { FirstGlyphIndex = contextualLookupsTable.SequenceIndex(fontTable.Wrapped, i), Transformations = this.GetTransformationTablesByLookupIndex(fontTable, contextualLookupsTable.LookupIndex(fontTable.Wrapped, i)) }).ToList() }); }
/// <summary> /// Dumps information about the specified typeface into console output stream. /// </summary> /// <param name="typeface">The typeface.</param> public void Dump(GlyphTypeface typeface) { dynamic fontTable = this.GetFontTable(typeface); dynamic fontTableHeader = this.GetFontTableHeader(); dynamic featureList = new AccessPrivateWrapper(fontTableHeader.GetFeatureList(fontTable.Wrapped)); dynamic lookupList = new AccessPrivateWrapper(fontTableHeader.GetLookupList(fontTable.Wrapped)); for (ushort i = 0; i < featureList.FeatureCount(fontTable.Wrapped); i++) { Console.WriteLine(i + " " + TagConverter.TagFromUint((uint)featureList.FeatureTag(fontTable.Wrapped, i)).Label); dynamic featureTable = new AccessPrivateWrapper(featureList.FeatureTable(fontTable.Wrapped, i)); for (ushort j = 0; j < featureTable.LookupCount(fontTable.Wrapped); j++) { dynamic lookupTable = new AccessPrivateWrapper(lookupList.Lookup(fontTable.Wrapped, featureTable.LookupIndex(fontTable.Wrapped, j))); var lookupFlags = (LookupFlags)lookupTable.LookupFlags(); var substitutionLookupType = (PositioningLookupType)lookupTable.LookupType(); Console.Write( "\t" + j + " " + lookupTable.offset + " " + featureTable.LookupIndex(fontTable.Wrapped, j) + " " + substitutionLookupType.ToString() + " "); if (substitutionLookupType == PositioningLookupType.ExtensionPositioning) { var type = typeof(GlyphTypeface).Assembly.GetType("MS.Internal.Shaping.ExtensionLookupTable"); var subTables = this.GetEnumerableFromInternalList( () => lookupTable.SubTableCount(), index => (dynamic) new AccessPrivateWrapper(type.Instantiate((ushort)lookupTable.SubtableOffset(fontTable.Wrapped, index)))); Console.Write(" [" + string.Join(", ", subTables.Select(subTable => ((PositioningLookupType)subTable.LookupType(fontTable.Wrapped)).ToString()).Distinct()) + "] "); } Console.Write("("); var flagsStrings = new List <string>(); if ((lookupFlags & LookupFlags.RightToLeft) == LookupFlags.RightToLeft) { flagsStrings.Add("RTL"); } if ((lookupFlags & LookupFlags.IgnoreBaseGlyphs) == LookupFlags.IgnoreBaseGlyphs) { flagsStrings.Add("IgnoreBaseGlyphs"); } if ((lookupFlags & LookupFlags.IgnoreLigatures) == LookupFlags.IgnoreLigatures) { flagsStrings.Add("IgnoreLigatures"); } if ((lookupFlags & LookupFlags.IgnoreMarks) == LookupFlags.IgnoreMarks) { flagsStrings.Add("IgnoreMarks"); } if ((lookupFlags & LookupFlags.UseMarkFilteringSet) == LookupFlags.UseMarkFilteringSet) { flagsStrings.Add("UseMarkFilteringSet"); } if ((lookupFlags & LookupFlags.MarkAttachmentTypeMask) > 0) { flagsStrings.Add("MarkAttachmentTypeMask=" + (lookupFlags & LookupFlags.MarkAttachmentTypeMask)); } Console.WriteLine(string.Join(", ", flagsStrings) + ") x" + lookupTable.SubTableCount()); } } }