Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / MS / Internal / Shaping / Substitution.cs / 1305600 / Substitution.cs
//+------------------------------------------------------------------------
//
// Microsoft Windows Client Platform
// Copyright (C) Microsoft Corporation, 2002
//
// File: Sustitution.cs
//
// Contents: OpentTypeLayout substitution classes
//
// contact: sergeym
//
// History: 2002-03-23 Created (sergeym)
//
//-----------------------------------------------------------------------
using System.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System;
using System.IO;
namespace MS.Internal.Shaping
{
//
[SecurityCritical(SecurityCriticalScope.Everything)]
internal struct SingleSubstitutionSubtable
{
private const int offsetFormat = 0;
private const int offsetCoverage = 2;
private const int offsetFormat1DeltaGlyphId = 4;
private const int offsetFormat2GlyphCount = 4;
private const int offsetFormat2SubstitutehArray = 6;
private const int sizeFormat2SubstituteSize = 2;
private ushort Format(FontTable Table)
{
return Table.GetUShort(offset + offsetFormat);
}
private CoverageTable Coverage(FontTable Table)
{
return new CoverageTable(offset+Table.GetUShort(offset + offsetCoverage));
}
private short Format1DeltaGlyphId(FontTable Table)
{
Invariant.Assert(Format(Table)==1);
return Table.GetShort(offset + offsetFormat1DeltaGlyphId);
}
// Not used. This value should be equal to glyph count in Coverage.
// Keeping it for future reference
//private ushort Foramt2GlyphCount(FontTable Table)
//{
// Debug.Assert(Format(Table)==2);
// return Table.GetUShort(offset + offsetFormat2GlyphCount);
//}
private ushort Format2SubstituteGlyphId(FontTable Table,ushort Index)
{
Invariant.Assert(Format(Table)==2);
return Table.GetUShort(offset + offsetFormat2SubstitutehArray +
Index * sizeFormat2SubstituteSize);
}
public bool Apply(
FontTable Table,
GlyphInfoList GlyphInfo, // List of GlyphInfo structs
int FirstGlyph, // where to apply it
out int NextGlyph // Next glyph to process
)
{
Invariant.Assert(FirstGlyph >= 0);
NextGlyph = FirstGlyph + 1; //In case we don't match;
ushort GlyphId = GlyphInfo.Glyphs[FirstGlyph];
int CoverageIndex = Coverage(Table).GetGlyphIndex(Table,GlyphId);
if (CoverageIndex == -1) return false;
switch(Format(Table))
{
case 1:
GlyphInfo.Glyphs[FirstGlyph] = (ushort)(GlyphId + Format1DeltaGlyphId(Table));
GlyphInfo.GlyphFlags[FirstGlyph] = (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
NextGlyph = FirstGlyph + 1;
return true;
case 2:
GlyphInfo.Glyphs[FirstGlyph] = Format2SubstituteGlyphId(Table,(ushort)CoverageIndex);
GlyphInfo.GlyphFlags[FirstGlyph] = (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
NextGlyph = FirstGlyph + 1;
return true;
default:
NextGlyph = FirstGlyph+1;
return false;
}
}
public bool IsLookupCovered(
FontTable table,
uint[] glyphBits,
ushort minGlyphId,
ushort maxGlyphId)
{
return Coverage(table).IsAnyGlyphCovered(table,
glyphBits,
minGlyphId,
maxGlyphId
);
}
public CoverageTable GetPrimaryCoverage(FontTable table)
{
return Coverage(table);
}
public SingleSubstitutionSubtable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
internal struct LigatureSubstitutionSubtable
{
private const int offsetFormat = 0;
private const int offsetCoverage = 2;
private const int offsetLigatureSetCount = 4;
private const int offsetLigatureSetArray = 6;
private const int sizeLigatureSet = 2;
private ushort Format(FontTable Table)
{
return Table.GetUShort(offset + offsetFormat);
}
private CoverageTable Coverage(FontTable Table)
{
return new CoverageTable(offset + Table.GetUShort(offset + offsetCoverage));
}
private ushort LigatureSetCount(FontTable Table)
{
return Table.GetUShort(offset + offsetLigatureSetCount);
}
private LigatureSetTable LigatureSet(FontTable Table, ushort Index)
{
return new LigatureSetTable(offset+Table.GetUShort(offset+
offsetLigatureSetArray +
Index * sizeLigatureSet));
}
#region Ligature Substitution subtable private structures
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
private struct LigatureSetTable
{
private const int offsetLigatureCount = 0;
private const int offsetLigatureArray = 2;
private const int sizeLigatureOffset = 2;
public ushort LigatureCount(FontTable Table)
{
return Table.GetUShort(offset + offsetLigatureCount);
}
public LigatureTable Ligature(FontTable Table, ushort Index)
{
return new LigatureTable(offset + Table.GetUShort(offset +
offsetLigatureArray +
Index * sizeLigatureOffset));
}
public LigatureSetTable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
private struct LigatureTable
{
private const int offsetLigatureGlyph = 0;
private const int offsetComponentCount = 2;
private const int offsetComponentArray = 4;
private const int sizeComponent = 2;
public ushort LigatureGlyph(FontTable Table)
{
return Table.GetUShort(offset + offsetLigatureGlyph);
}
public ushort ComponentCount(FontTable Table)
{
return Table.GetUShort(offset + offsetComponentCount);
}
public ushort Component(FontTable Table, ushort Index)
{
//LigaTable includes comps from 1 to N. So, (Index-1)
return Table.GetUShort(offset + offsetComponentArray +
(Index-1) * sizeComponent);
}
public LigatureTable(int Offset) { offset = Offset; }
private int offset;
}
#endregion
public unsafe bool Apply(
IOpenTypeFont Font,
FontTable Table,
int CharCount,
UshortList Charmap, // Character to glyph map
GlyphInfoList GlyphInfo, // List of GlyphInfo
ushort LookupFlags, // Lookup flags for glyph lookups
int FirstGlyph, // where to apply it
int AfterLastGlyph, // how long is a context we can use
out int NextGlyph // Next glyph to process
)
{
Invariant.Assert(FirstGlyph>=0);
Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length);
NextGlyph = FirstGlyph + 1; //In case we don't match;
if (Format(Table) != 1) return false; // Unknown format
int glyphCount=GlyphInfo.Length;
ushort glyphId = GlyphInfo.Glyphs[FirstGlyph];
int CoverageIndex = Coverage(Table).GetGlyphIndex(Table,glyphId);
if (CoverageIndex==-1) return false;
int curGlyph;
ushort ligatureGlyph=0;
bool match = false;
ushort compCount=0;
LigatureSetTable ligatureSet = LigatureSet(Table,(ushort)CoverageIndex);
ushort ligaCount = ligatureSet.LigatureCount(Table);
for(ushort liga=0; liga=AfterLastGlyph) break;
if (GlyphInfo.Glyphs[curGlyph]!=ligature.Component(Table,comp)) break;
}
if (comp==compCount) //liga matched
{
match=true;
ligatureGlyph = ligature.LigatureGlyph(Table);
break; //Liga found
}
}
//If no ligature found, match will remain false after last iteration
if (match)
{
//Fix character and glyph Mapping
//PERF: localize ligature character range
//Calculate Ligature CharCount
int totalLigaCharCount=0;
int firstLigaChar=int.MaxValue;
curGlyph=FirstGlyph;
for(ushort comp=0;comp0)
{
for(int glyph=prevGlyph+1; glyph1) //do fixing only if have glyphs in between
{
for(int curChar=0; curCharprevGlyph && curCharmap 1)
{
GlyphInfo.Remove(GlyphInfo.Length-compCount+1,compCount-1);
}
NextGlyph=prevGlyph-(compCount-1)+1;
}
return match;
}
public bool IsLookupCovered(
FontTable table,
uint[] glyphBits,
ushort minGlyphId,
ushort maxGlyphId)
{
if (!Coverage(table).IsAnyGlyphCovered(table,
glyphBits,
minGlyphId,
maxGlyphId
)
) return false;
ushort ligatureSetCount = LigatureSetCount(table);
for(ushort setIndex = 0; setIndex < ligatureSetCount; setIndex++)
{
LigatureSetTable ligatureSet = LigatureSet(table, setIndex);
ushort ligaCount = ligatureSet.LigatureCount(table);
for (ushort liga = 0; liga < ligaCount; liga++)
{
LigatureTable ligature = ligatureSet.Ligature(table, liga);
ushort compCount = ligature.ComponentCount(table);
bool ligatureIsComplex = true;
for(ushort compIndex = 1; compIndex < compCount; compIndex++)
{
ushort glyphId = ligature.Component(table,compIndex);
if (glyphId > maxGlyphId ||
glyphId < minGlyphId ||
(glyphBits[glyphId >> 5] & (1 << (glyphId % 32))) == 0
)
{
ligatureIsComplex = false;
break;
}
}
if (ligatureIsComplex) return true;
}
}
return false;
}
public CoverageTable GetPrimaryCoverage(FontTable table)
{
return Coverage(table);
}
public LigatureSubstitutionSubtable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
internal struct MultipleSubstitutionSequenceTable
{
private const int offsetGlyphCount = 0;
private const int offsetGlyphArray = 2;
private const int sizeGlyphId = 2;
public ushort GlyphCount(FontTable Table)
{
return Table.GetUShort(offset + offsetGlyphCount);
}
public ushort Glyph(FontTable Table, ushort index)
{
return Table.GetUShort(offset + offsetGlyphArray + index * sizeGlyphId);
}
public MultipleSubstitutionSequenceTable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
internal struct MultipleSubstitutionSubtable
{
private const int offsetFormat = 0;
private const int offsetCoverage = 2;
private const int offsetSequenceCount = 4;
private const int offsetSequenceArray = 6;
private const int sizeSequenceOffset = 2;
private ushort Format(FontTable Table)
{
return Table.GetUShort(offset + offsetFormat);
}
private CoverageTable Coverage(FontTable Table)
{
return new CoverageTable(offset + Table.GetUShort(offset + offsetCoverage));
}
// Not used. This value should be equal to glyph count in Coverage.
// Keeping it for future reference
//private ushort SequenceCount(FontTable Table)
//{
// return Table.GetUShort(offset + offsetSequenceCount);
//}
private MultipleSubstitutionSequenceTable Sequence(FontTable Table, int Index)
{
return new MultipleSubstitutionSequenceTable(
offset +
Table.GetUShort(offset +
offsetSequenceArray +
Index * sizeSequenceOffset)
);
}
public unsafe bool Apply(
IOpenTypeFont Font,
FontTable Table,
int CharCount,
UshortList Charmap, // Character to glyph map
GlyphInfoList GlyphInfo, // List of GlyphInfo
ushort LookupFlags, // Lookup flags for glyph lookups
int FirstGlyph, // where to apply it
int AfterLastGlyph, // how long is a context we can use
out int NextGlyph // Next glyph to process
)
{
NextGlyph = FirstGlyph + 1; // in case we don't match
if (Format(Table) != 1) return false; //unknown format
int oldGlyphCount=GlyphInfo.Length;
ushort glyphId = GlyphInfo.Glyphs[FirstGlyph];
int coverageIndex = Coverage(Table).GetGlyphIndex(Table,glyphId);
if (coverageIndex==-1) return false;
MultipleSubstitutionSequenceTable sequence = Sequence(Table,coverageIndex);
ushort sequenceLength = sequence.GlyphCount(Table);
int lengthDelta = sequenceLength - 1;
if (sequenceLength==0)
{
// This is illegal, because mapping will be broken -
// corresponding char will be lost. Just leave it as it is.
// (char will be attached to the following glyph).
GlyphInfo.Remove(FirstGlyph,1);
}
else
{
ushort firstChar = GlyphInfo.FirstChars[FirstGlyph];
ushort ligatureCount = GlyphInfo.LigatureCounts[FirstGlyph];
if (lengthDelta > 0)
{
GlyphInfo.Insert(FirstGlyph,lengthDelta);
}
//put glyphs in place
for(ushort gl=0; gl base and marks decomposition
//
for(int ch=0;chFirstGlyph) Charmap[ch] = (ushort)(Charmap[ch]+lengthDelta);
}
NextGlyph = FirstGlyph + lengthDelta + 1;
return true;
}
public bool IsLookupCovered(
FontTable table,
uint[] glyphBits,
ushort minGlyphId,
ushort maxGlyphId)
{
return Coverage(table).IsAnyGlyphCovered(table,
glyphBits,
minGlyphId,
maxGlyphId
);
}
public CoverageTable GetPrimaryCoverage(FontTable table)
{
return Coverage(table);
}
public MultipleSubstitutionSubtable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
struct AlternateSubstitutionSubtable
{
private const int offsetFormat = 0;
private const int offsetCoverage = 2;
private const int offsetAlternateSetCount = 4;
private const int offsetAlternateSets = 6;
private const int sizeAlternateSetOffset = 2;
private const ushort InvalidAlternateGlyph = 0xFFFF;
public ushort Format(FontTable Table)
{
return Table.GetUShort(offset + offsetFormat);
}
private CoverageTable Coverage(FontTable Table)
{
return new CoverageTable(offset + Table.GetUShort(offset + offsetCoverage));
}
// Not used. This value should be equal to glyph count in Coverage.
// Keeping it for future reference
//private ushort AlternateSetCount(FontTable Table)
//{
// return Table.GetUShort(offset + offsetAlternateSetCount);
//}
private AlternateSetTable AlternateSet(FontTable Table, int index)
{
return new AlternateSetTable(offset +
Table.GetUShort(offset +
offsetAlternateSets +
index * sizeAlternateSetOffset)
);
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
private struct AlternateSetTable
{
private const int offsetGlyphCount = 0;
private const int offsetGlyphs = 2;
private const int sizeGlyph = 2;
public ushort GlyphCount(FontTable Table)
{
return Table.GetUShort(offset + offsetGlyphCount);
}
public ushort Alternate(FontTable Table, uint FeatureParam)
{
Invariant.Assert(FeatureParam > 0); // Parameter 0 means feautre is disabled.
//Should be filtered out in GetNextEnabledGlyphRange
// Off by one - alternate number 1 is stored under index 0
uint index = FeatureParam - 1;
if (index >= GlyphCount(Table))
{
return AlternateSubstitutionSubtable.InvalidAlternateGlyph;
}
return Table.GetUShort(offset + offsetGlyphs + (ushort)index*sizeGlyph);
}
public AlternateSetTable(int Offset) { offset = Offset; }
private int offset;
}
public unsafe bool Apply(
FontTable Table,
GlyphInfoList GlyphInfo, // List of GlyphInfo
uint FeatureParam, // For this lookup - index of glyph alternate
int FirstGlyph, // where to apply it
out int NextGlyph // Next glyph to process
)
{
NextGlyph = FirstGlyph + 1; // always move one glyph forward,
// doesn't matter whether we matched context
if (Format(Table) != 1) return false; //Unknown format
int oldGlyphCount=GlyphInfo.Length;
int coverageIndex = Coverage(Table).
GetGlyphIndex(Table,GlyphInfo.Glyphs[FirstGlyph]);
if (coverageIndex==-1) return false;
AlternateSetTable alternateSet = AlternateSet(Table,coverageIndex);
ushort alternateGlyph = alternateSet.Alternate(Table, FeatureParam);
if (alternateGlyph != InvalidAlternateGlyph)
{
GlyphInfo.Glyphs[FirstGlyph] = alternateGlyph;
GlyphInfo.GlyphFlags[FirstGlyph] = (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
return true;
}
return false;
}
public bool IsLookupCovered(
FontTable table,
uint[] glyphBits,
ushort minGlyphId,
ushort maxGlyphId)
{
return Coverage(table).IsAnyGlyphCovered(table,
glyphBits,
minGlyphId,
maxGlyphId
);
}
public CoverageTable GetPrimaryCoverage(FontTable table)
{
return Coverage(table);
}
public AlternateSubstitutionSubtable(int Offset) { offset = Offset; }
private int offset;
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//+------------------------------------------------------------------------
//
// Microsoft Windows Client Platform
// Copyright (C) Microsoft Corporation, 2002
//
// File: Sustitution.cs
//
// Contents: OpentTypeLayout substitution classes
//
// contact: sergeym
//
// History: 2002-03-23 Created (sergeym)
//
//-----------------------------------------------------------------------
using System.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System;
using System.IO;
namespace MS.Internal.Shaping
{
//
[SecurityCritical(SecurityCriticalScope.Everything)]
internal struct SingleSubstitutionSubtable
{
private const int offsetFormat = 0;
private const int offsetCoverage = 2;
private const int offsetFormat1DeltaGlyphId = 4;
private const int offsetFormat2GlyphCount = 4;
private const int offsetFormat2SubstitutehArray = 6;
private const int sizeFormat2SubstituteSize = 2;
private ushort Format(FontTable Table)
{
return Table.GetUShort(offset + offsetFormat);
}
private CoverageTable Coverage(FontTable Table)
{
return new CoverageTable(offset+Table.GetUShort(offset + offsetCoverage));
}
private short Format1DeltaGlyphId(FontTable Table)
{
Invariant.Assert(Format(Table)==1);
return Table.GetShort(offset + offsetFormat1DeltaGlyphId);
}
// Not used. This value should be equal to glyph count in Coverage.
// Keeping it for future reference
//private ushort Foramt2GlyphCount(FontTable Table)
//{
// Debug.Assert(Format(Table)==2);
// return Table.GetUShort(offset + offsetFormat2GlyphCount);
//}
private ushort Format2SubstituteGlyphId(FontTable Table,ushort Index)
{
Invariant.Assert(Format(Table)==2);
return Table.GetUShort(offset + offsetFormat2SubstitutehArray +
Index * sizeFormat2SubstituteSize);
}
public bool Apply(
FontTable Table,
GlyphInfoList GlyphInfo, // List of GlyphInfo structs
int FirstGlyph, // where to apply it
out int NextGlyph // Next glyph to process
)
{
Invariant.Assert(FirstGlyph >= 0);
NextGlyph = FirstGlyph + 1; //In case we don't match;
ushort GlyphId = GlyphInfo.Glyphs[FirstGlyph];
int CoverageIndex = Coverage(Table).GetGlyphIndex(Table,GlyphId);
if (CoverageIndex == -1) return false;
switch(Format(Table))
{
case 1:
GlyphInfo.Glyphs[FirstGlyph] = (ushort)(GlyphId + Format1DeltaGlyphId(Table));
GlyphInfo.GlyphFlags[FirstGlyph] = (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
NextGlyph = FirstGlyph + 1;
return true;
case 2:
GlyphInfo.Glyphs[FirstGlyph] = Format2SubstituteGlyphId(Table,(ushort)CoverageIndex);
GlyphInfo.GlyphFlags[FirstGlyph] = (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
NextGlyph = FirstGlyph + 1;
return true;
default:
NextGlyph = FirstGlyph+1;
return false;
}
}
public bool IsLookupCovered(
FontTable table,
uint[] glyphBits,
ushort minGlyphId,
ushort maxGlyphId)
{
return Coverage(table).IsAnyGlyphCovered(table,
glyphBits,
minGlyphId,
maxGlyphId
);
}
public CoverageTable GetPrimaryCoverage(FontTable table)
{
return Coverage(table);
}
public SingleSubstitutionSubtable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
internal struct LigatureSubstitutionSubtable
{
private const int offsetFormat = 0;
private const int offsetCoverage = 2;
private const int offsetLigatureSetCount = 4;
private const int offsetLigatureSetArray = 6;
private const int sizeLigatureSet = 2;
private ushort Format(FontTable Table)
{
return Table.GetUShort(offset + offsetFormat);
}
private CoverageTable Coverage(FontTable Table)
{
return new CoverageTable(offset + Table.GetUShort(offset + offsetCoverage));
}
private ushort LigatureSetCount(FontTable Table)
{
return Table.GetUShort(offset + offsetLigatureSetCount);
}
private LigatureSetTable LigatureSet(FontTable Table, ushort Index)
{
return new LigatureSetTable(offset+Table.GetUShort(offset+
offsetLigatureSetArray +
Index * sizeLigatureSet));
}
#region Ligature Substitution subtable private structures
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
private struct LigatureSetTable
{
private const int offsetLigatureCount = 0;
private const int offsetLigatureArray = 2;
private const int sizeLigatureOffset = 2;
public ushort LigatureCount(FontTable Table)
{
return Table.GetUShort(offset + offsetLigatureCount);
}
public LigatureTable Ligature(FontTable Table, ushort Index)
{
return new LigatureTable(offset + Table.GetUShort(offset +
offsetLigatureArray +
Index * sizeLigatureOffset));
}
public LigatureSetTable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
private struct LigatureTable
{
private const int offsetLigatureGlyph = 0;
private const int offsetComponentCount = 2;
private const int offsetComponentArray = 4;
private const int sizeComponent = 2;
public ushort LigatureGlyph(FontTable Table)
{
return Table.GetUShort(offset + offsetLigatureGlyph);
}
public ushort ComponentCount(FontTable Table)
{
return Table.GetUShort(offset + offsetComponentCount);
}
public ushort Component(FontTable Table, ushort Index)
{
//LigaTable includes comps from 1 to N. So, (Index-1)
return Table.GetUShort(offset + offsetComponentArray +
(Index-1) * sizeComponent);
}
public LigatureTable(int Offset) { offset = Offset; }
private int offset;
}
#endregion
public unsafe bool Apply(
IOpenTypeFont Font,
FontTable Table,
int CharCount,
UshortList Charmap, // Character to glyph map
GlyphInfoList GlyphInfo, // List of GlyphInfo
ushort LookupFlags, // Lookup flags for glyph lookups
int FirstGlyph, // where to apply it
int AfterLastGlyph, // how long is a context we can use
out int NextGlyph // Next glyph to process
)
{
Invariant.Assert(FirstGlyph>=0);
Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length);
NextGlyph = FirstGlyph + 1; //In case we don't match;
if (Format(Table) != 1) return false; // Unknown format
int glyphCount=GlyphInfo.Length;
ushort glyphId = GlyphInfo.Glyphs[FirstGlyph];
int CoverageIndex = Coverage(Table).GetGlyphIndex(Table,glyphId);
if (CoverageIndex==-1) return false;
int curGlyph;
ushort ligatureGlyph=0;
bool match = false;
ushort compCount=0;
LigatureSetTable ligatureSet = LigatureSet(Table,(ushort)CoverageIndex);
ushort ligaCount = ligatureSet.LigatureCount(Table);
for(ushort liga=0; liga=AfterLastGlyph) break;
if (GlyphInfo.Glyphs[curGlyph]!=ligature.Component(Table,comp)) break;
}
if (comp==compCount) //liga matched
{
match=true;
ligatureGlyph = ligature.LigatureGlyph(Table);
break; //Liga found
}
}
//If no ligature found, match will remain false after last iteration
if (match)
{
//Fix character and glyph Mapping
//PERF: localize ligature character range
//Calculate Ligature CharCount
int totalLigaCharCount=0;
int firstLigaChar=int.MaxValue;
curGlyph=FirstGlyph;
for(ushort comp=0;comp0)
{
for(int glyph=prevGlyph+1; glyph1) //do fixing only if have glyphs in between
{
for(int curChar=0; curCharprevGlyph && curCharmap 1)
{
GlyphInfo.Remove(GlyphInfo.Length-compCount+1,compCount-1);
}
NextGlyph=prevGlyph-(compCount-1)+1;
}
return match;
}
public bool IsLookupCovered(
FontTable table,
uint[] glyphBits,
ushort minGlyphId,
ushort maxGlyphId)
{
if (!Coverage(table).IsAnyGlyphCovered(table,
glyphBits,
minGlyphId,
maxGlyphId
)
) return false;
ushort ligatureSetCount = LigatureSetCount(table);
for(ushort setIndex = 0; setIndex < ligatureSetCount; setIndex++)
{
LigatureSetTable ligatureSet = LigatureSet(table, setIndex);
ushort ligaCount = ligatureSet.LigatureCount(table);
for (ushort liga = 0; liga < ligaCount; liga++)
{
LigatureTable ligature = ligatureSet.Ligature(table, liga);
ushort compCount = ligature.ComponentCount(table);
bool ligatureIsComplex = true;
for(ushort compIndex = 1; compIndex < compCount; compIndex++)
{
ushort glyphId = ligature.Component(table,compIndex);
if (glyphId > maxGlyphId ||
glyphId < minGlyphId ||
(glyphBits[glyphId >> 5] & (1 << (glyphId % 32))) == 0
)
{
ligatureIsComplex = false;
break;
}
}
if (ligatureIsComplex) return true;
}
}
return false;
}
public CoverageTable GetPrimaryCoverage(FontTable table)
{
return Coverage(table);
}
public LigatureSubstitutionSubtable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
internal struct MultipleSubstitutionSequenceTable
{
private const int offsetGlyphCount = 0;
private const int offsetGlyphArray = 2;
private const int sizeGlyphId = 2;
public ushort GlyphCount(FontTable Table)
{
return Table.GetUShort(offset + offsetGlyphCount);
}
public ushort Glyph(FontTable Table, ushort index)
{
return Table.GetUShort(offset + offsetGlyphArray + index * sizeGlyphId);
}
public MultipleSubstitutionSequenceTable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
internal struct MultipleSubstitutionSubtable
{
private const int offsetFormat = 0;
private const int offsetCoverage = 2;
private const int offsetSequenceCount = 4;
private const int offsetSequenceArray = 6;
private const int sizeSequenceOffset = 2;
private ushort Format(FontTable Table)
{
return Table.GetUShort(offset + offsetFormat);
}
private CoverageTable Coverage(FontTable Table)
{
return new CoverageTable(offset + Table.GetUShort(offset + offsetCoverage));
}
// Not used. This value should be equal to glyph count in Coverage.
// Keeping it for future reference
//private ushort SequenceCount(FontTable Table)
//{
// return Table.GetUShort(offset + offsetSequenceCount);
//}
private MultipleSubstitutionSequenceTable Sequence(FontTable Table, int Index)
{
return new MultipleSubstitutionSequenceTable(
offset +
Table.GetUShort(offset +
offsetSequenceArray +
Index * sizeSequenceOffset)
);
}
public unsafe bool Apply(
IOpenTypeFont Font,
FontTable Table,
int CharCount,
UshortList Charmap, // Character to glyph map
GlyphInfoList GlyphInfo, // List of GlyphInfo
ushort LookupFlags, // Lookup flags for glyph lookups
int FirstGlyph, // where to apply it
int AfterLastGlyph, // how long is a context we can use
out int NextGlyph // Next glyph to process
)
{
NextGlyph = FirstGlyph + 1; // in case we don't match
if (Format(Table) != 1) return false; //unknown format
int oldGlyphCount=GlyphInfo.Length;
ushort glyphId = GlyphInfo.Glyphs[FirstGlyph];
int coverageIndex = Coverage(Table).GetGlyphIndex(Table,glyphId);
if (coverageIndex==-1) return false;
MultipleSubstitutionSequenceTable sequence = Sequence(Table,coverageIndex);
ushort sequenceLength = sequence.GlyphCount(Table);
int lengthDelta = sequenceLength - 1;
if (sequenceLength==0)
{
// This is illegal, because mapping will be broken -
// corresponding char will be lost. Just leave it as it is.
// (char will be attached to the following glyph).
GlyphInfo.Remove(FirstGlyph,1);
}
else
{
ushort firstChar = GlyphInfo.FirstChars[FirstGlyph];
ushort ligatureCount = GlyphInfo.LigatureCounts[FirstGlyph];
if (lengthDelta > 0)
{
GlyphInfo.Insert(FirstGlyph,lengthDelta);
}
//put glyphs in place
for(ushort gl=0; gl base and marks decomposition
//
for(int ch=0;chFirstGlyph) Charmap[ch] = (ushort)(Charmap[ch]+lengthDelta);
}
NextGlyph = FirstGlyph + lengthDelta + 1;
return true;
}
public bool IsLookupCovered(
FontTable table,
uint[] glyphBits,
ushort minGlyphId,
ushort maxGlyphId)
{
return Coverage(table).IsAnyGlyphCovered(table,
glyphBits,
minGlyphId,
maxGlyphId
);
}
public CoverageTable GetPrimaryCoverage(FontTable table)
{
return Coverage(table);
}
public MultipleSubstitutionSubtable(int Offset) { offset = Offset; }
private int offset;
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
struct AlternateSubstitutionSubtable
{
private const int offsetFormat = 0;
private const int offsetCoverage = 2;
private const int offsetAlternateSetCount = 4;
private const int offsetAlternateSets = 6;
private const int sizeAlternateSetOffset = 2;
private const ushort InvalidAlternateGlyph = 0xFFFF;
public ushort Format(FontTable Table)
{
return Table.GetUShort(offset + offsetFormat);
}
private CoverageTable Coverage(FontTable Table)
{
return new CoverageTable(offset + Table.GetUShort(offset + offsetCoverage));
}
// Not used. This value should be equal to glyph count in Coverage.
// Keeping it for future reference
//private ushort AlternateSetCount(FontTable Table)
//{
// return Table.GetUShort(offset + offsetAlternateSetCount);
//}
private AlternateSetTable AlternateSet(FontTable Table, int index)
{
return new AlternateSetTable(offset +
Table.GetUShort(offset +
offsetAlternateSets +
index * sizeAlternateSetOffset)
);
}
///
/// Critical - Everything in this struct is considered critical
/// because they either operate on raw font table bits or unsafe pointers.
///
[SecurityCritical(SecurityCriticalScope.Everything)]
private struct AlternateSetTable
{
private const int offsetGlyphCount = 0;
private const int offsetGlyphs = 2;
private const int sizeGlyph = 2;
public ushort GlyphCount(FontTable Table)
{
return Table.GetUShort(offset + offsetGlyphCount);
}
public ushort Alternate(FontTable Table, uint FeatureParam)
{
Invariant.Assert(FeatureParam > 0); // Parameter 0 means feautre is disabled.
//Should be filtered out in GetNextEnabledGlyphRange
// Off by one - alternate number 1 is stored under index 0
uint index = FeatureParam - 1;
if (index >= GlyphCount(Table))
{
return AlternateSubstitutionSubtable.InvalidAlternateGlyph;
}
return Table.GetUShort(offset + offsetGlyphs + (ushort)index*sizeGlyph);
}
public AlternateSetTable(int Offset) { offset = Offset; }
private int offset;
}
public unsafe bool Apply(
FontTable Table,
GlyphInfoList GlyphInfo, // List of GlyphInfo
uint FeatureParam, // For this lookup - index of glyph alternate
int FirstGlyph, // where to apply it
out int NextGlyph // Next glyph to process
)
{
NextGlyph = FirstGlyph + 1; // always move one glyph forward,
// doesn't matter whether we matched context
if (Format(Table) != 1) return false; //Unknown format
int oldGlyphCount=GlyphInfo.Length;
int coverageIndex = Coverage(Table).
GetGlyphIndex(Table,GlyphInfo.Glyphs[FirstGlyph]);
if (coverageIndex==-1) return false;
AlternateSetTable alternateSet = AlternateSet(Table,coverageIndex);
ushort alternateGlyph = alternateSet.Alternate(Table, FeatureParam);
if (alternateGlyph != InvalidAlternateGlyph)
{
GlyphInfo.Glyphs[FirstGlyph] = alternateGlyph;
GlyphInfo.GlyphFlags[FirstGlyph] = (ushort)(GlyphFlags.Unresolved | GlyphFlags.Substituted);
return true;
}
return false;
}
public bool IsLookupCovered(
FontTable table,
uint[] glyphBits,
ushort minGlyphId,
ushort maxGlyphId)
{
return Coverage(table).IsAnyGlyphCovered(table,
glyphBits,
minGlyphId,
maxGlyphId
);
}
public CoverageTable GetPrimaryCoverage(FontTable table)
{
return Coverage(table);
}
public AlternateSubstitutionSubtable(int Offset) { offset = Offset; }
private int offset;
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- WaitHandleCannotBeOpenedException.cs
- ElementUtil.cs
- WorkflowStateRollbackService.cs
- AuthenticationConfig.cs
- Delegate.cs
- _ShellExpression.cs
- RunWorkerCompletedEventArgs.cs
- XmlUTF8TextReader.cs
- CTreeGenerator.cs
- DesignerDataSourceView.cs
- DependencyPropertyChangedEventArgs.cs
- SurrogateSelector.cs
- ParamArrayAttribute.cs
- DataGrid.cs
- MsmqIntegrationProcessProtocolHandler.cs
- Comparer.cs
- TimeSpan.cs
- SqlStream.cs
- XmlDataSource.cs
- SegmentInfo.cs
- PropertyDescriptor.cs
- AggregateException.cs
- GZipUtils.cs
- HttpProfileGroupBase.cs
- HtmlCalendarAdapter.cs
- ConfigurationLocation.cs
- Container.cs
- ObjectViewFactory.cs
- MailMessage.cs
- SQLMoneyStorage.cs
- ErrorFormatterPage.cs
- ToggleButton.cs
- BindingCompleteEventArgs.cs
- ForwardPositionQuery.cs
- TypeDescriptorContext.cs
- OracleFactory.cs
- CommandBindingCollection.cs
- dsa.cs
- FunctionDetailsReader.cs
- SQLString.cs
- AnonymousIdentificationModule.cs
- MetadataFile.cs
- XamlPointCollectionSerializer.cs
- UIAgentAsyncParams.cs
- FixedSchema.cs
- _KerberosClient.cs
- OneOfElement.cs
- ArraySortHelper.cs
- AppearanceEditorPart.cs
- SpecialNameAttribute.cs
- SpecialNameAttribute.cs
- ZipIORawDataFileBlock.cs
- ExpressionBindingCollection.cs
- MetabaseSettings.cs
- Opcode.cs
- ZipIOLocalFileDataDescriptor.cs
- ServiceRoute.cs
- ZoneMembershipCondition.cs
- MultipleViewProviderWrapper.cs
- XmlValidatingReader.cs
- GridViewDeleteEventArgs.cs
- XmlSerializerFactory.cs
- NestPullup.cs
- CustomExpressionEventArgs.cs
- PropertyTab.cs
- TextElement.cs
- AttributeSetAction.cs
- FixedSchema.cs
- RegisteredDisposeScript.cs
- OdbcFactory.cs
- EpmHelper.cs
- ListParaClient.cs
- SvcMapFile.cs
- SqlComparer.cs
- DoubleConverter.cs
- AlphabetConverter.cs
- KernelTypeValidation.cs
- IPAddressCollection.cs
- AddInController.cs
- AbandonedMutexException.cs
- TaiwanLunisolarCalendar.cs
- SQLDecimalStorage.cs
- EntityDataSourceStatementEditorForm.cs
- StartUpEventArgs.cs
- ModuleBuilderData.cs
- TextSegment.cs
- SrgsOneOf.cs
- XslUrlEditor.cs
- TimeSpanValidator.cs
- PropertyExpression.cs
- DrawingAttributesDefaultValueFactory.cs
- ServicePoint.cs
- cache.cs
- BooleanProjectedSlot.cs
- ControlCachePolicy.cs
- HistoryEventArgs.cs
- SafeFileMappingHandle.cs
- DesignerDataColumn.cs
- DataSourceGroupCollection.cs
- ProcessProtocolHandler.cs